レンダリング後に 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()
使う方法毎回ググってたのでメモ
[参考]
今期は 逃げ上手の若君 を観ておけばよいですか?