レンダリング後に useEffect で何かしらの初期化処理を行って、完了したことを明示したい時など 1回だけ更新する state を作りたいケース
別に useState でも良いのだけれど、useState は setter が返されるので state を自由に更新できてしまうので、state の値を reducer 関数でコントロールできる useReducer を使うパターン
useReducer()
const [state, dispatch] = useReducer(reducer, initialArg, init?);
useReducer は state を更新する reducer 関数と state の初期値 initialArg を取って、state と reducer を呼び出す為の dispatch を返す
📝: init? は初期 state を返す初期化関数。指定されている場合は初期値が init(initialArg) の結果となる
reducer 関数
const reducer = (currentState, value) => newState;
reducer 関数は、現在の state と dispatch に渡される値 (value) を引数にとり、新しい state の値を返す関数であれば良い
useReducer() で 1回だけ更新される state を作る
1回だけ更新される state を作成するには reducer が常に同じ値を返せば良い
import { useEffect, useState, useReducer } from 'react'; const useLocalStorage = () => { const [isPending, complete] = useReducer(() => false, true); const [value, setValue] = useState<LodacStorageData | undefined>(undefined); useEffect(() => { complete(); const data = localStorage.getItem(LOCALSTORAGE_KEY); // localStorage に値が存在しない場合 if (data === null) { return; } try { const v = JSON.parse(data) as LodacStorageData; setValue(v); } catch { localStorage.removeItem(LOCALSTORAGE_KEY); } }, []); return {isPending, storageData: value}; }
useReducer() を使って toggle になる state を実装する
reducer 関数には現在の state が渡されることを利用すると toggle になる state が簡単に作れる
import { useReducer } from "react"; export const useToggle = (initialValue: boolean = true) => { const [toggleState, onToggle] = useReducer((state) => !state, initialValue); return { toggleState, onToggle, }; }; const App = () => { const { toggleState, onToggle } = useToggle(); return <button onClick={onToggle}>{toggleState ? 'ON' : 'OFF'}</button> }
Sample
useReucer() 使う方法毎回ググってたのでメモ
[参考]
今期は 逃げ上手の若君 を観ておけばよいですか?

