Reactの基本まとめ（Hooks含む）

最終的にReactでTodoリストを構築します。
Reduxなどの状態管理ライブラリは含みません。

# Reactとは
Reactは、クライアントサイドでWebページのレンダリングを行うサイト[SPA（Single Page Application）](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)を構築する際に便利なライブラリーです。
SPAでは、Webページ表示後も引き続きクライアント側でコンテンツの表示非表示等の状態管理を、継続的に行う必要があります。
Reactでは、予めJSによるロジックとHTMLがセットになった部品（コンポーネント）を用意しておき、それらを組み合わせることでWebページを構成する、コンポーネントベースと呼ばれる考え方を採用しています。
Reactは内部でJSのロジックと対応するDOM要素をマッピングしており、JS側の処理に応じて自動でDOM要素を更新してくれます。
このあたりの仕組みは仮想DOMと呼ばれています。

静的ページやサーバーサイドレンダリングのページでは、引き続き[jQuery](https://jquery.com/)も便利かなと思っています。

[Reactの本家サイト](https://ja.reactjs.org/)は、最近日本語にも対応しておりとても充実しています。
ここのチュートリアルを一通り実践することもお勧めいたします。

**※**Node.jsとnpmの利用環境が既に整っていることを前提としています。
[Node.js / npmをインストールする（for Windows）](https://qiita.com/taiponrock/items/9001ae194571feb63a5e)
過去に投稿したこちらの記事でも触れています。
[Node.jsとExpressでローカルサーバーを構築する(1) ―Node.jsとnpmの導入―](https://qiita.com/koedamon/items/37ea8e9175cf0fd62371)

# 環境構築
React公式では、[Create React App](https://facebook.github.io/create-react-app/)というスターターキットを用意しています。
今回は、簡単にはじめられる[Parcel](https://ja.parceljs.org/)を利用して環境を構築したいと思います。

## インストール
React本体と、ReactとDOM要素をつなげるためのReactDOMをインストールします。

```sh
$ npm install --save react react-dom
```

引き続き、ParcelとBabelのReact用プリセットをインストールします。

```sh
$ npm install --save-dev parcel-bundler @babel/preset-react
```

## トランスパイラ
Reactは、通常のJavaScript構文だけで構築することも可能ですが、基本的にJSXと呼ばれる構文を利用するのが一般的です。
ブラウザに導入されているわけではないので、[トランスパイラ](https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9)と呼ばれるツールを用いてJavaScripの構文に変換（トランスパイル）する必要があります。
このトランスパイルには一般的に[Babel](https://babeljs.io/)というツールが用いられます。

公式提供スターターキットのCreateReactAppでも内部でBabelが利用されているようです。
Babel自体は、自分で色々設定が出来る自由度の高いツールであると同時に、設定が面倒なツールでもあります。
ParcelはこのBabelを内包した上で、細かな設定をせずともすぐに使えるように作られています。
プリセットは、Babelのオプション用パッケージのことを指します。
ReactのJSXのトランスパイルはオプション機能として提供されている為、別途インストールが必要です。
Parcelの場合、インストールするだけで設定は特に不要です。

## バンドラ
es2015にて、JavaScripにモジュール機能(ESModules)が導入されました。
用途ごとに分割された外部JSファイルを、[import](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/import)・[export](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/export)文を通して利用する仕組みです。
HTMLファイル上での読み込み順序を気にすることなく、JS側でファイルの依存関係の管理が完結します。
また、各モジュール毎に[スコープ](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97)が閉じているので、ファイル間での名前の衝突の心配がなくなります。

既にブラウザに機能導入が進んでいるようです。
対象のJSファイルを読み込む際に`<script type="module">`とすると、ESModulesの対象となります。
ただ、読み込むファイル数が増えればリクエストの回数も増えてしまうので、今のところモジュールバンドラーというツールを用いて、ある程度まとめてしまう（バンドルする）のが一般的です。

モジュールバンドラーは色々ありますが、特に人気なのは[webpack](https://webpack.js.org/)でしょうか。
webpackもBabelと同様、自由度が高い分、設定の手間が多いツールです。
実は、Parcelはバンドルもしてくれます。
こちらも細かな設定は不要なので、インストールした時点でほぼほぼ環境構築が完了しています。

[JavaScript modules | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Modules)
webpackとBabelについては、過去に投稿した記事もございます。
[webpackとBabelの基本を理解する(1) ―webpack編―](https://qiita.com/koedamon/items/3e64612d22f3473f36a4)

# Reactコンポーネントの基本
## JSXをHTMLで出力する
ひとまず、Reactを使って何かしらのHTMLを出力してみましょう。
下記のフォルダ構成でファイルを用意します。
ファイルの拡張子は`js`以外に`jsx`も使えます。

```
root
  └ src
      ├ index.html
      └ index.jsx
```

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>React Todo</title>
</head>
<body>
  <div id="root"></div>
  <script src="index.jsx"></script>
</body>
</html>
```

```jsx
// Reactパッケージの読み込み
import React from 'react';
import ReactDOM from 'react-dom';

// Reactコンポーネント
class App extends React.Component {
  render() {
    return (
      <h1>Hello React!</h1>
    );
  }
}

// HTMLタグにReactコンポーネントを紐付ける
ReactDOM.render(
  <App />,
  document.getElementById('root')
);
```

rootフォルダで下記コマンドを実行してみます。

```sh
npx parcel src/index.html
```

### Parcelによるバンドル
初回は`./dist`フォルダが作成され、html,js,mapファイルが出力されています。
コマンドで指定したhtmlをスタート地点として、`<script>`で読み込んでいるJSファイルから`import`文を頼りに芋づる式に辿って、一つのファイルにまとめていきます。
出力されたJSファイルには暫定的な名前がつけられ、HTMLファイルの方もこれを参照するように書き換わっています。
mapファイルは、元ファイルと出力後ファイルのコードの対応を示す情報です。
ブラウザのDevToolなどでデバッグする際に、元ファイルの方を参照することが出来ます。

実は、Parcelはテストサーバも立ち上げてくれます。
コンソールに出力されたローカルサーバのURLにアクセスすると、出力を確認できます。
また、特に指定をしなければwatchモードで起動する為、関連ファイルを編集すると勝手にコンパイル（トランスパイルとバンドル）を実行してくれます。

![reactTodo1.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362737/bb13dd3b-dc0b-0fc6-91b3-75ae54a25cec.gif)

### カスタムコンポーネント
`React.Component`クラスを継承した[サブクラス](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%96%E3%82%AF%E3%83%A9%E3%82%B9_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%A6))`App`が、ユーザ定義のReactコンポーネント（カスタムコンポーネント）です。
名前は大文字で始める必要があります。
`App`クラスの`render`というメソッドにて、戻り値を定義している部分に書かれているHTMLのようなものがJSXです。
正確にはXMLに近く、空要素には必ずスラッシュ`/`を入れる必要があります。

[React.Component | React](https://ja.reactjs.org/docs/react-component.html)

### ReactDOM
ReactコンポーネントとDOM要素をつなぐ役割を果たします。
上記の例では、静的メソッド`render`を利用して、`<div id="root">`配下にAPPで定義したHTMLが展開されるようにしています。

[ReactDOM | React](https://ja.reactjs.org/docs/react-dom.html)

## 対話による状態変更
ボタンのクリックに応じて、文字が切り替わるようにしてみます。

```jsx
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isMorning: true
    };
  }
  render() {
    return (
      <div>
        <button
          onClick={e => {
            this.setState(
              { isMorning: !this.state.isMorning }
            );
          }}
        >
          Click
        </button>
        <h1>
          {this.state.isMorning ? 'Good Morning' : 'Hello'} React!
        </h1>
      </div>
    );
  }
}
```

`button`タグをクリックする度に文字が切り替わるようになりました。
このコンポーネントは、内部で状態`isMorning`を保持・管理しています。
クリックすると`isMorning`の状態が切り替わり、それに応じてHTMLも再レンダリングされます。

![reactTodo2.GIF](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362737/2fdc9b01-2e97-4448-4a54-f687e7c977a9.gif)

`render`メソッド内のJSXの部分が、通常のHTMLとは様子が異なってきました。
`onClick`はHTMLタグの`onclick`属性とは異なる、JSX側の構文です。
用途は`onclick`属性と同様、HTML要素にイベントハンドラを設置する為のものです。
`h1`のテキストコンテンツ部分には、JSの三項演算子が追加されました。
`isMorning`の値に応じて異なる文字列を返すようにしています。

つまりHTMLにJSのコードを埋め込んだものがJSXです。
埋め込み部分は波括弧`{ }`で囲みます。
PHPなどでテンプレートページを作る時と要領は似ており、JSの実行結果がHTML上に描画されます。
コンテンツのデータ、そのデータの処理ロジック、描画が一通りセットになったオブジェクトがReactコンポーネントです。
このコンポーネントを適宜組み合わせることで、状況に応じたWebページを表現します。

[JSXの導入 | React](https://ja.reactjs.org/docs/introducing-jsx.html)

## renderメソッド
サブクラスで必ず定義しなくてはならないのが、`render`メソッドです。
`render`メソッドでは、コンテンツをどう描画するのかをJSXなどで定義した情報を返す必要があります。
コンテンツに変更があれば、Reactは`render`メソッドを呼び出し、定義に基づいてコンテンツに紐づくHTML要素を更新します。
この際、全体を丸ごと更新するのではなく、差分を確認して必要な部分のみ更新してくれます。

**※**差分の確認およびDOM要素の更新は、ReactDOMが担っています。

[render() | React](https://ja.reactjs.org/docs/react-component.html#render)

## stateとsetState
前項で「コンテンツに変更があれば」と表しましたが、`render`メソッドにの実行に関わる情報は、厳密にはコンポーネントの「状態」を表す情報です。
このコンポーネントの「状態」を表す情報は、クラスの`state`プロパティとして、[コンストラクタ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes/constructor)内で定義します。
そして、この`state`プロパティを更新する専用メソッド`setState`を利用して、コンポーネントの状態を更新します。
すると`render`メソッドが呼び出され、`state`に紐づくHTML要素が再レンダリングされます。
プロパティを`state`以外の名前で定義したり、直接更新するなどの`setState`メソッド以外の手段で`state`を更新した場合、`render`は呼ばれません。

上記サンプルコードにてボタンがクリックされた時に行っていることは、状態の変更だけです。
`this.state.isMorning`の値を変更しているだけです。
`isMorning`の値に紐づいている`h1`タグは、Reactが勝手に更新してくれます。
HTMLのDOM要素を直接管理する手間から開放され、JavaScript上でのデータ管理を気にかけるだけで済みます。

### setStateを利用したstateの更新例
setStateで渡されたstateの断片は、最終的に`this.state`にマージされます。
配列を利用する場合は一旦複製する必要があります。

```js
// stateを複数定義する
this.state = {
  stateA: 'hoge',
  stateB: [ 'cat', 'dog' ]
};

// 特定のstateを更新する
this.setState({
  stateA: 'moimoi'
});

// 配列の場合は、一旦複製
const stateB = this.state.stateB.slice();
stateB.push('rabbit');
this.setState({ stateB });

// 下記では再描画が発生しない
this.state.stateB.push('rabbit');
this.setState({ 
  stateB: this.state.stateB
});
```

Reactは、更新内容を最小限にとどめる為に差分チェックをします。
`setState`を実行しても、前回と値に変わりが無ければ再レンダリングされません。
その際は[Object.is](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/is)のアルゴリズムに基づいて比較を行います。
配列は、保存されたメモリの位置でざっくりと比較されるので、新規配列を渡す必要があります。

```js
const stateA = ['cat', 'dog'];

const stateB = stateA;  //stateAもstateBも同じ配列を参照している
const stateC = stateA.slice();

stateB.push('rabbit');
stateC.push('rabbit');

console.log(Object.is(stateA, stateB)); // true
console.log(Object.is(stateA, stateC)); // false
```

[setState() | React](https://ja.reactjs.org/docs/react-component.html#setstate)
[state とライフサイクル | React](https://ja.reactjs.org/docs/state-and-lifecycle.html)

## イベント処理
イベントハンドラに無名関数を渡すのではなく、クラスのメソッドを設定する場合は以下のようになります。
Reactに限った話ではありませんが、イベントリスナーを登録する際に`element.addEventListener('click', this.someMethod)`の要領でメソッドをそのまま渡しても、コールバックで実行された関数内での`this`の参照はそのメソッドが属するオブジェクトにはなりません。
素のJSでは、イベントを登録したDOM要素がthisになります。Reactの場合は`undefined`でした。
その為、コンストラクタ内にて[bindメソッド](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)で所定のオブジェクトを`this`として参照する関数を生成して、上書きしています。

```jsx
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isMorning: true
    };
    // コールバック関数内で、thisの参照がこのクラスを指すための設定
    this.handleClick = this.handleClick.bind(this);
  }
  // クリック時のハンドラ
  handleClick(e) {
    this.setState(
      { isMorning: !this.state.isMorning }
    );
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick} >
          Click
        </button>
        <h1>
          {this.state.isMorning ? 'Good Morning' : 'Hello'} React!
        </h1>
      </div>
    );
  }
}
```

無名関数を直接渡す場合は、[アロー関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)を利用します。

[イベント処理 | React](https://ja.reactjs.org/docs/handling-events.html)

## propsによるデータの受け渡し
複数のコンポーネントを組み合わせてこそのReactなので、ボタンを別のコンポーネントとして切り出してみます。

```jsx
// 子コンポーネント
// ボタンコンポーネント
class MyButton extends React.Component {
  // state等の宣言をしない場合は省略可
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <button onClick={this.props.onClick} >
        {this.props.text}
      </button>
    );
  }
}

// 親コンポーネント
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isMorning: true
    };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(e) {
    this.setState(
      { isMorning: !this.state.isMorning }
    );
  }
  // <button>の代わりに<MyButton />
  render() {
    return (
      <div>
        {/* 文字列とイベントハンドラを渡す */} 
        <MyButton text="Click" onClick={this.handleClick} />
        <h1>
          {this.state.isMorning ? 'Good Morning' : 'Hello'} React!
        </h1>
      </div>
    );
  }
}
```

JSX上で、一つのタグとしてコンポーネント名を記述します。
この際、子コンポーネントとなるコンポーネントに値を渡すことが出来ます。
受け取った側のコンポーネントは、`this.props`からこの値にアクセスできます。
コンストラクタ内で受け取っている`props`がそうです。
`this.props`は読み取り専用です。`this.state`の様に更新することは出来ません。
`this.props`もまた、更新されると`render`メソッドが呼び出され、紐づくDOM要素が再レンダリングされます。

外部から渡される読み取り専用データ`props`と、内部で管理する制御データ`state`、この二つがコンポーネントのレンダリング実行に関係します。

尚、Reactコンポーネントが大文字で始める必要があるのは、通常のHTMLタグと区別する為です。
`<div>`はhtmlのdivタグとして認識されますが、`<Div>`はReactコンポーネントと見なされます。
スコープ内に該当コンポーネントが無い場合はエラーになります。

## 関数コンポーネント
上記ボタンコンポーネントは、内部で状態`state`を持ちません。
受け取った`props`をJSXで展開するのみです。
この場合、クラス構文ではなく関数の構文で定義する方が好ましいです。

```jsx
// 一つの連想配列でpropsを受け取る
function MyButton(props) {
  return (
    <button onClick={props.onClick} >
      {props.text}
    </button>
  );
}

// 分割代入が便利
function MyButton({ onClick, text }) {
  return (
    <button onClick={onClick} >
      {text}
    </button>
  );
}
```

`render`メソッドと同じく、JSXを返します。
Reactがインポートされているモジュール内であれば、そのままReactコンポーネントとして認識されます。

## Hooks
ReactのVer.16.8から、新機能Hooksが導入されました。
Hooksは、関数コンポーネントに追加できる様々な機能群です。
クラスコンポーネントでしか出来なかったことが、関数コンポーネントでも出来るようになります。
公式によると、クラスコンポーネントはトランスパイル後のソースにて、関数コンポーネントほど最適化されていないようです。
今のところクラスコンポーネントを将来的に廃止するとかそういう話にはなっていませんが、これからはシンプルな関数コンポーネントの組み合わせによる構成が推奨されているようです。

[フックの導入 | React](https://ja.reactjs.org/docs/hooks-intro.html)

### ステートフック
ステートフックは関数コンポーネントにも内部状態を持たせる仕組みです。
これまで、stateを保持する場合はクラスコンポーネント、保持しない場合は関数コンポーネントと使い分けていたのが、Hooksを利用すると関数コンポーネントでもstateを持つことが出来ます。

上記のクラスコンポーネント`App`をHookを利用した関数コンポーネントに書き換えてみます。

```jsx
import React, { useState } from 'react';

function App() {
  // useStateの引数はstateの初期値
  const [isMorning, toggleFlag] = useState(false);

  return (
    <div>
      <MyButton
        onClick={e => toggleFlag(!isMorning)}
        text="Click"
      />
      <h1>
        {isMorning ? 'Good Morning' : 'Hello'} React!
      </h1>
    </div>

  );
}
```

`useState`関数をインポートして利用します。
必ず、**関数コンポーネント直下のスコープ**で実行する必要があります。
引数はstateの初期値です。
戻り値は配列です。0番目が現在のstate、1番目がstateを更新する為の関数です。分割代入で受け取っています。
それぞれ、クラスコンポーネントの`this.state`と`this.setState`と同じ役割を果たします。
初回実行時は`useState`の引数で渡した初期値をstateとして受け取ります。
2回目以降は現在のstateの値（更新用関数で更新した場合は更新後の値）を受け取ります。
必要に応じて複数のstateを用意することも出来ますし、クラスコンポーネントの様に一つのオブジェクトで管理する事もできます。

```js
function Example() {
  // 別々にstateを用意する
  const [count, setCount] = useState(0);
  const [animal, setAnimal] = useState(['cat']);

  // もしくは一つのオブジェクトで定義
  // 但し、this.setStateとは異なり、古いものにマージされるのではなく置換されるので注意
  const [state, setState] = useState({
    count: 0,
    animal: ['cat']
  });
```

[ステートフックの利用法 | React](https://ja.reactjs.org/docs/hooks-state.html)

**自己定義関数**
useState関数はレンダリングの度に実行されますが、引数が有効なのは初回レンダリング時のみです。
実際に中のソースがどうなっているのかは分かりませんが、挙動としては自己定義関数が近いでしょうか。

```js
let animal = (first) => {
  // 初回しか実行されない処理
  console.log(first);
  // 自らを上書き
  animal = () => {
    // 2回目以降に実行される処理
    console.log('cat!');
  };
};

animal('dog!'); // dog!
animal('dog!'); // cat!
animal('dog!'); // cat!
```

# Todoアプリ
シンプルなTodoアプリを作成します。

![ReactTodo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362737/408ccc10-f54c-c68b-e665-cc172a75f2bf.gif)

## Todoリストを表示する
ひとまず、予め用意したTodoリストを表示するコンポーネントを作成します。
リストは配列で管理します。

```jsx
import React, { useState } from 'react';
import ReactDOM from 'react-dom';

// Todo項目
function Todo({ text }) {
  const [completed, setState] = useState(false);

  return (
    <li
      onClick={e => setState(!completed)}
      style={{
        textDecoration: completed ? 'line-through' : 'none'
      }}
    >
      {text}
    </li>
  );
}

// Todoリスト
function TodoList() {
  const [todos, setTodo] = useState(
    [
      '牛乳 2本',
      '卵 10ヶ入 1パック',
      '食パン 5枚切り 1袋'
    ]
  );

  // todosを基に<Todo />の配列を作成
  return (
    <ul>
      {todos.map((todo, index) => (
        <Todo key={index} text={todo} />
      ))}
    </ul>
  );
}

ReactDOM.render(
  <TodoList />,
  document.getElementById('root')
);
```

コンポーネント`Todo`は、一つのtodo項目を表します。
完了の状態を保持し、クリックすると完了を示す打ち消し線が表示され、再度クリックすると未完了の状態になります。
JSXにてstyle属性を適用したい場合は、オブジェクト`{style名:値}`を渡します。
`text-decoration`の様なハイフン`-`を含む名前は、ローワーキャメルケースで指定します。

コンポーネント`TodoList`は、todoリストを保持します。
配列をJSX内で展開する場合は[map](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)メソッドを利用します。
その際、`key`値も指定する必要があります。
keyはReactが内部でリストの各要素を識別する為に用いる為、リスト内で一意の値でなくてはなりません。
固有のID等の値が無い場合、配列のインデックス値を適用することも可能ですが、インデックスは随時振りなおされるものなので、あまりお勧めは出来ません。

[リストと key | React](https://ja.reactjs.org/docs/lists-and-keys.html)

## Todoを追加する
Todoを自分で入力するためのコンポーネントを追加します。

```jsx
function Todo({ text }) {
  /* 変更なし */
}

// Todoを追加する
function AddTodo({ addTodo }) {
  const [inputText, setInputText] = useState('');

  return (
    <form
      onSubmit={e => {
        e.preventDefault(); // 素のJSのEvent.preventDefault()と同じ
        if (!inputText.trim()) {
          return;
        }
        addTodo(inputText);
        setInputText('');
      }}
    >
      <input
        type="text"
        value={inputText}
        onChange={e => setInputText(e.target.value)}
      />
      <button type="submit">Add Todo</button>
    </form>
  );
}

// Todoリスト
function TodoList() {
  const [todos, setTodo] = useState([]);

  return (
    <div>
      <AddTodo addTodo={newTodo => setTodo(todos.concat(newTodo))} />
      <ul>
        {todos.map((todo, index) => (
          <Todo key={index} text={todo} />
        ))}
      </ul>
    </div>
  );
}
```

ReactにてInputフォームを利用するにあたり、Input要素の状態(value属性の値)を管理する為のstateを用意しています。
入力値を受け取り`todos`を更新する関数を、propsを通して`TodoList`から`AddTodo`に渡しています。

### Ref
DOM要素に直接アクセスする方法として、Refがあります。
`React.createRef()`メソッドを利用して`Ref`を作成します。
その`Ref`を対象のReact要素の`ref`属性に設定すると、`current`プロパティを通してDOM要素に直接アクセスすることが可能になります。

```jsx
function AddTodo({ addTodo }) {
  let textInput = React.createRef();

  return (
    <form
      onSubmit={e => {
        e.preventDefault();
        const elInput = textInput.current;
        if (!elInput.value.trim()) {
          return;
        }
        addTodo(elInput.value);
        elInput.value = '';
      }}
    >
      <input
        type="text"
        ref={textInput}
      />
      <button type="submit">Add Todo</button>
    </form>
  );
}
```

HTML要素ではなく、カスタムクラスコンポーネントの`ref`属性に`Ref`を適用した場合、`curret`プロパティでアクセスできるのは、そのクラスのインスタンスです。
関数コンポーネントはインスタンスが存在しない為、`ref`属性は利用できません。
あまり多用するとReactを利用するメリットが薄くなるので、基本的にはstateとpropsを通して管理するのが望ましいです。

[RefとDOM](https://ja.reactjs.org/docs/refs-and-the-dom.html)

## Todoに表示フィルタを追加する
Todoリストを「全て・完了・未完了」で切り替えられるよう、フィルター機能を追加します。

```jsx
// 表示切替用フィルタ
const VisibilityFilters = {
  SHOW_ALL: 'All',
  SHOW_COMPLETED: 'Completed',
  SHOW_ACTIVE: 'Active'
};

function Todo({ text, filter }) {
  const [completed, setState] = useState(false);

  if (
    (filter === VisibilityFilters.SHOW_ACTIVE && completed)
    || (filter === VisibilityFilters.SHOW_COMPLETED && !completed)
  ) {
    // 表示対象外の場合はnullを返す(非表示)
    return null;
  }

  return (
    <li
      onClick={e => setState(!completed)}
      style={{
        textDecoration: completed ? 'line-through' : 'none'
      }}
    >
      {text}
    </li>
  );
}

function AddTodo({ addTodo }) {
  /* 変更なし */
}

// フィルターボタン
function Link({ active, onClick, children }) {
  // 予めオブジェクトで定義して展開するのもあり
  const params = {
    onClick: onClick,
    disabled: active,
    style: { marginLeft: '4px' }
  };

  return (
    <button {...params}>
      {children}
    </button>
  );
}

// 表示の切替
function Footer({ filter, setFilter }) {
  const linkList = Object.values(VisibilityFilters);

  return (
    <div>
      {linkList.map(myFilter => (
        <Link
          key={myFilter}
          active={myFilter === filter}
          onClick={e => setFilter(myFilter)}
        >
          {myFilter}
        </Link>
      ))}
    </div>
  );
}

// Todoリスト
function TodoList() {
  const [todos, setTodo] = useState([]);
  const [filter, setFilter] = useState(VisibilityFilters.SHOW_ALL);

  return (
    <div>
      <AddTodo addTodo={newTodo => setTodo(todos.concat(newTodo))} />
      <ul>
        {todos.map((todo, index) => (
          <Todo
            key={index}
            text={todo}
            filter={filter}
          />
        ))}
      </ul>
      <Footer filter={filter} setFilter={setFilter} />
    </div>
  );
}
```

`TodoList`に、現在のフィルターを表す新たなstate`filter`を追加しました。
`Todo`コンポーネント内では、フィルターと項目の完了状態が一致しない場合に`null`を返すようにしています。
`null`を返すと、そのコンポーネントはレンダリングの対象から外れます。

### props.children
Reactコンポーネントは、空要素以外にコンテンツを閉じタグで囲って記述することも可能です。
この場合、子要素は`props.children`で取得できます。
他のReactコンポーネントを渡すことも可能で、コンポーネントのネストが深くなることを防ぐことが出来ます。

```jsx
function Child(props) {
  return <p>{props.children}</p>
}

function OtherChild(props) {
  return <span>{props.text}</span>
}

function Parent() {
  return (
    <Child>
      <OtherChild text="HOGE" />
    </Child>
  );
}

//<p>
//  <span>HOGE</span>
//</p>
```

[props.children | React](https://ja.reactjs.org/docs/glossary.html#propschildren)

# Flux
上記例では、Todoのテキストのリストは`TodoList`コンポーネントが、項目ごとの完了未完了の状態は`Todo`コンポーネントが保持しています。
大きなアプリケーションでは、このstateが各コンポーネントに散らばっていることで、管理が煩雑になってしまうかもしれません。
Reactを提供するFaceBookでは、アプリケーションの状態を一元的に管理する設計手法として、[Flux](https://facebook.github.io/flux/)という考え方を提示しています。

Fluxに関しては、以前に投稿したこちらの記事がございます。

- [FluxによるReactアプリの状態管理 Flux・FluxUtils編](https://qiita.com/koedamon/items/6bca2375feec89c66359)
- [FluxによるReactアプリの状態管理 Redux・React-Redux編](https://qiita.com/koedamon/items/fe24f17374dc1d24c7fe)
- [FluxによるReactアプリの状態管理 ReactHooks編](https://qiita.com/koedamon/items/13df746dd82f760a0247)

# デベロッパーツール
公式からデバッグ用ツールが提供されています。

- [GoogleChrome アドオン](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=ja)
- [Firefox アドオン](https://addons.mozilla.org/ja/firefox/addon/react-devtools/)
- [スタンドアロン(Safari等)](https://github.com/facebook/react-devtools/blob/master/packages/react-devtools/README.md)