React & TypeScript初学者のすゝめ 第四章

## Reactにおける状態管理
Reactの強みであるStateについて、その機能のおかげでリアルタイムのフォーム処理を行うことができたり、プログラムの自由度が増したが、その一方で変数が複数になりタコ足回線のようなPropsの渡し合いでプログラムの複雑さが増した。
そのため必要となったのが土台の部分でStateを管理する機能である。有名なものには**Redux**や**Recoil**がある。

## Recoilによる状態管理
アプリケーションの中で使うStateはAtomという保管場所で管理を行う(Reduxで言うStoreの概念)。
srcフォルダの下にatomsフォルダを作り、その下にatomファイルを置く。
```atomState.tsx
import { atom } from 'recoil'

export const textState = atom({
  key: 'textState', // アプリケーション全体で使うキー
  default: '',     // 初期値
});
// 同じファイルに複数のStateを設定することも可能
export const numState = atom({
  key: 'numState',
  default: 0,
})
```
この値の呼び出し方に行く前に、最初にRecoilでStateを扱う場合に適用範囲を定めるため、useContextのようにタグで囲う。
```App.tsx
import { RecoilRoot } from 'recoil'
import { TextInput } from './components/TextInput'
import { CharacterCount } from './components/CharacterCount'

class App extends React.Component {
  render(){
    return (
    <RecoilRoot>
      <TextInput />
      <CharacterCount />
    </RecoilRoot>
    )
  }
}
export default App;
```
実際にRecoilを使った処理について
```TextInput.tsx
import { useRecoilState } from 'recoil'
import { textState, numState } from '../atoms/atomState'

export const TextInput = () => {
  const [text, setText] = useRecoilState(textState);
  const [num, setNum] = useRecoilState(numState);
  // 入力値でAtomを更新
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value);
  }
  const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setNum(Number(e.target.value));
  }
  return(
    <div>
      <input type="text" onChange={handleChange} />
      <select value={num} onChange={handleSelectChange}>
        <option value="0">0</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
      </select>
      {/*Reactにおいて<br>は閉じてない判定されるため使わないように*/}
      <br />
      出力: {text}
      出力(セレクト): {num}
    </div>
  );
};
```
AtomからStateを引っ張ってきてuseRecoilState関数に引き渡すだけで、簡単にStateとセット関数を取ってこれる。

## Selectorを使ってみる
RecoilではAtomに変数を設定するだけではなく、Selectorという機能を使うことでAtomに格納しているStateを編集して返す、より自由度の高い状態管理を実現できる。

まずAtom同様にsrcフォルダの下にselectorフォルダを作成し、selectorファイルを置く。
```charCountState.tsx
import { selector } from 'recoil'
import { textState, numState } from '../atoms/atomState'

export const charCountState = selector({
  key: 'charCountState',
  //Atomの値を加工して返す関数を設定、GetRecoilValue型のgetを引数
  get: ({get}) => {
    const text = get(textState)
    //加工した値を返す
    return text.length
  }
})
export const sumNumState = selector({
  key: 'sumNumState',
  get: ({get}) => {
    const text = get(textState);
    const num = get(numState);
    //加工した値を返す
    return text.length * num
  }
})
```
Atomと似ているが、getの部分で計算処理などをさせることができる。
そして、それを機能としてアプリケーションの中に実装する部分については
```CharacterCount.tsx
import { useRecoilValue } from 'recoil'
import { charCountState, sumNumState } from '../selectors/selectorState'

export const CharacterCount = () => {
  // stateとset関数を取得するuseRecoilState関数と違いstate取得のみを行う
  const count = useRecoilValue(charCountState)
  const sum = useRecoilValue(sumNumState)
  
  return (
    <div>
     <p>文字数：{count}</p>
     <p>合計：{sum}</p>
    </div>
  );
}
```
このようにRecoilを使えばuseContextを使うよりも簡単にクラス間やページ間の値の受け渡しができるため、Reactの開発において絶対不可欠の機能だと思われる。
同様の機能にReduxというものもあるが、こちらの方が主流ではあるがルールが多く構造も複雑になるため、大規模開発でもしない限りはRecoilの方が良いだろうと考える。

#### 以上、四章に渡ってReactの最低限知っておかなければならない知識をおさらいした。これから先もReactはWebプログラムの中心的存在であり続けるので続けるので注視して行きたい。