Reactハンズオン 備忘録


はじめに

社内勉強会で共有した内容の備忘録です。
勉強会の元ネタは「Reactハンズオンラーニング 第2版――Webアプリケーション開発のベストプラクティス」です。

Angular, Vue.jsを触ったことのある方がReactを触ると、Javascriptの中にHTMLを書くことに違和感を感じるかもしれません。ただし、ReactコンポーネントはJavaScriptの関数であること、違和感を感じるのはJSX記法によるものだということが理解できるとReactに親しみを感じれるかと思い、先日の勉強会では

  • 関数型プログラミング
  • 宣言型プログラミング

について触れました
この記事はその時の勉強会の内容の備忘録です。

React概要

JavaScriptフレームワークとして、Angular, Vue.js, Reactが良く比較の対象になりますが、それらの違いは何でしょうか。

一つReactが他のフレームワークと違うところがあるとするならば、それがフレームワークではなくてライブラリであるということです。

FrameworkとLibraryの違いについて以下のブログが読みやすかったです。

Digitalya - Is React a framework or library? - Everything you need to know

Reactは公式サイトでライブラリであると定義されており、Reactが何かというと

A JavaScript library for building user interfaces

ユーザーインターフェースを作るためのJavaScript Libararyです。
JavaScriptにはdocument.createElement(), document.appendChildといったDOM APIがデフォルトで提供されていますが、これらの機能を一手に引き受けるライブラリがReactだと理解していただいて問題ないかと思います。

Reactを理解するために必要な概念としてはVirtual DOMとJSXがあると考えられます。

Virtual DOMはプログラミングのパターンであり、Virtual DOM自体はReactの実装の一部です。

また、JSXはプログラムの書き方であり、ReactコンポーネントはJSX式と呼ばれたりします。
式と呼ばれることからわかるようにReactコンポーネントは関数でありJSXは書き方です。

Virtual DOM

リアルDomに書き込む前に仮想Dom同士で比較をしてからRenderingするので、描画速度が早い。
Vueでも仮想Domの仕組みが使われている。

VueはReactと同じ仮想DOMのパターンが使われており、AngularはリアルDOMが使われています。
AngularのRenderlingの仕組みについて述べたブログの中では、仮想Domはメモリの消費が激しいというデメリットが挙げられている。

以下のブログはAngularの開発者が書いた記事でリアルDOMのメリットが述べられています。
Medium - Introducing Incremental DOM

JSX JSの中にXMLのようなタグベースの記述をすることができる。

複雑なDomツリーと属性を簡単に記述できるようにすることを目的で導入された。

JSXはHTMLと似ているが別物。

ポイント:JSXはBabelを使って一度JSへコンパイルされている。

宣言的に書ける

Reactを使うと宣言的にUIを定義することができます。以下の記事ではVue.jsが使われていますが、Reactでも同じことが言えます。

zenn - 宣言的UIが何か分からなかったので調べてみた

Wikiの説明には
宣言型は副作用を排除した純粋関数の実装に努めると書かれていますが、純粋関数については勉強会では触れていなかったので各自で調べてみてください。

理想的には人ではなくて機械に頑張ってもらうのがあるべき姿だと思うので、そのようにプログラムを組めるのが宣言的プログラミングのメリットだと思います。

宣言的プログラミングについてはWikiの説明が良かったです。
wiki - 宣言型プログラミング

命令型 VS 宣言型

宣言的とはプログラムに”What”を書くことで命令的とは”How”を書くことです。具体的な例としては以下のようなものになります。

var string = "Restrant in Tokyo";
var urlFriendly = "";

for (var i = 0; i < string.length; i++) {
	if (string[i] === " ") {
		urlFriendly += "-";
	} else {
		urlFriendly += string[i];
	}
}

上記のプログラムは「URLに空白が含まれていてはいけない」ということを”知っていれば”読むことができるプログラムですが、その前提を知らない人はプログラムを読むのに苦労すると思います。対して宣言的に書くと以下のようになります。

var string = "Restaurants in Tokyo.";
var urlFriendly = string.replace(/ /g, "-");

上記のコードでは”状態”を書いているので「URLに空白が含まれていてはいけない」という前提を知らなくても理解ができるプログラムです。
今回は「URLに空白が含まれていてはいけない」という既に共有されている前提で例えましたが、これが業務ロジックであったとしても同じことが言えると思います。

ここまでが宣言的に書くことのメリットでしたが、Reactは宣言的にコンポーネントが定義できることが一つの特徴です。

*2019年2月6日 hookが追加
関数の中でデータにアクセスするAPIが作られたことで、複雑なロジックを関数に書くことができるようになった。

Release v16.8.0 · facebook/react

関数型プログラミング

コンポーネントと props - React

Reactのコンポーネントは関数ととてもよく似ています。

関数型について

下記のようにして関数を変数として扱うことができます。

const log = function(message){
	console.log(message)
}

以下は高階関数と呼ばれる書き方で、Reactコンポーネントでも同じ書き方が良く用いられます。

const createScream = logger => message => {
    logger(message.toUpperCase() + "!!!");
}

scream = createScream(message => console.log(message));

scream('functions can be returned from other functions');
scream('createScream returns a function');
scream('scream invokes that returned function');

Reactコンポーネントを見慣れていない方は、その書き方を独特に感じるかもしれませんが、根本的にはJavaScriptの関数だと理解するとReactについての理解が進むかと思います。