useReducer
複雑になったらuseReducerを使おう、って説明になってないでしょ

「複雑になったら」ってなんやねん
本質をついている感じがしないので腑に落ちない
tsconst [state, dispatch] = useReducer(reducer, initialArg, init);
第1引数
reducer
type Reducer<S, A> = (prevState: S, action: A) => S;
例.tsfunction reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
第2引数
stateの初期値
第3引数
初期値を遅延初期化するために使う関数
useStateの引数に関数を渡すのと同じイメージ
初期stateは init(initialArg)
の結果になる
コード例
tstype State = {
count: number;
};
type Action = {
type: 'increment' | 'decrement';
};
function init(initialCount: number): State {
return { count: initialCount };
}
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
throw new Error();
}
}
type CounterProps = {
initialCount: number;
};
const Counter: React.FC<CounterProps> = ({ initialCount }) => {
const [state, dispatch] = React.useReducer(reducer, initialCount, init);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
);
};
useReducerを使うことで、状態がreducerの中に閉じる
それによって、 useCallback
などのdepsにstateを入れずに済むため、パフォ改善につながる