【React】普段よくuseStateを使ってるけど、useReducer使いたくなった✋

2022/09/03に公開

https://ja.reactjs.org/docs/hooks-reference.html#usereducer
https://zenn.dev/tis1116/articles/8b04672a0221bb
上記ドキュメント、zennを参考にしました。 useReducer使いたくなりました! 感謝です!

useReducerは useStateの代替品で、useStateと同じようにコンポーネントを状態管理できるようになります。

useReducerを使うべき条件

複数の値にまたがる複雑な state ロジックがある場合や、前の state に基づいて次の state を決める必要がある場合

useReducerを使うメリット

コールバックの代わりに dispatch を下位コンポーネントに渡せるようになる
ステイトの更新ロジックを分離することができる
reducerの単体テストが可能になる

useReducerを使った具体例

  • checkboxのvalueを配列(State)に保存する。
  • 配列の要素がダブらないように、ステイトを更新する際に適宜条件分岐を行いユニークな状態を保つ。
checkbox_useReducer.js
import React, { useReducer } from "react";
import Checkboxes from "../components/checkboxes";
import reducer from "../lib/function/checkboxReducer";

const checkbox_useReducer = () => {
  const [checkboxState, dispatch] = useReducer(reducer, []);
  return <Checkboxes clickCheckBox={dispatch} />;
};

export default checkbox_useReducer;
checkboxReducer
const reducer = (state, action) => {
  if (state.includes(action)) {
    return (state = state.filter((item) => item != action));
  } else {
    return (state = [...state, action]);
  }
};

export default reducer;
checkboxes.js
import React, { memo } from "react";
const Checkboxes = ({ clickCheckBox }) => {
  return (
    <div>
      <label>jordan1</label>
      <input
        type="checkbox"
        value="jordan1"
        onChange={(e) => clickCheckBox(e.target.value)}
      />
      <label>jordan2</label>
      <input
        type="checkbox"
        value="jordan2"
        onChange={(e) => clickCheckBox(e.target.value)}
      />
      <label>jordan3</label>
      <input
        type="checkbox"
        value="jordan3"
        onChange={(e) => clickCheckBox(e.target.value)}
      />
    </div>
  );
};

export default memo(Checkboxes);

コールバック関数を子コンポーネント(memo化している状態)に渡すと、例えコールバック関数の処理が同じだったとしても、違う関数と判断されてしまいます。しかしdispatchの場合

再レンダー間で dispatch 関数の同一性が保たれ、変化しないことを保証します。

上記のようにドキュメントに記載があり、dispatchを渡す子コンポーネントでmemo化を行うことで無駄なレンダリングを防ぐことができます。

Discussion