rerender-functional-setstate について
React 開発者向けのコーディングスキルです。現在の state に依存する更新では関数形式の `setState` を推奨します。古いクロージャを防ぎ、依存関係を減らしてコールバックを安定させる方法を説明します。
主な機能
- 01最新の state 値に基づく更新
- 02古いクロージャの防止
- 03コールバックの安定化
- 04Hook の依存関係の削減
活用シーン
- 01state 配列への項目追加
- 02コールバック内での state 更新
- 03イベントハンドラーや非同期処理での state 変更
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ theorcdev/ 8bitcn-ui --skill rerender-functional-setstateインストール後、Claude Code で/rerender-functional-setstateを入力して読み込まれたか確認します。
詳細
関数型の setState 更新を使用する
現在の状態値に基づいて状態を更新する場合は、状態変数を直接参照するのではなく、setState の関数型更新形式を使用してください。これにより、古いクロージャを防ぎ、不要な依存関係をなくし、安定したコールバック参照を作成できます。
誤った例(状態を依存関係に指定する必要があります):
function TodoList() {
const [items, setItems] = useState(initialItems)
// Callback must depend on items, recreated on every items change
const addItems = useCallback((newItems: Item[]) => {
setItems([...items, ...newItems])
}, [items]) // items dependency causes recreations
// Risk of stale closure if dependency is forgotten
const removeItem = useCallback((id: string) => {
setItems(items.filter(item => item.id !== id))
}, []) // Missing items dependency - will use stale items!
return <ItemsEditor items={items} onAdd={addItems} onRemove={removeItem} />
}
最初のコールバックは items が変わるたびに再作成されるため、子コンポーネントが不必要に再レンダリングされる可能性があります。2つ目のコールバックには古いクロージャのバグがあり、常に初期値の items を参照します。
正しい例(安定したコールバック、古いクロージャなし):
function TodoList() {
const [items, setItems] = useState(initialItems)
// Stable callback, never recreated
const addItems = useCallback((newItems: Item[]) => {
setItems(curr => [...curr, ...newItems])
}, []) // No dependencies needed
// Always uses latest state, no stale closure risk
const removeItem = useCallback((id: string) => {
setItems(curr => curr.filter(item => item.id !== id))
}, []) // Safe and stable
return <ItemsEditor items={items} onAdd={addItems} onRemove={removeItem} />
}
メリット:
- 安定したコールバック参照 - 状態が変わってもコールバックを再作成する必要がありません
- 古いクロージャなし - 常に最新の状態値を使用します
- 依存関係の削減 - 依存配列を簡潔にし、メモリリークを減らします
- バグの防止 - React のクロージャに関する最も一般的なバグの原因を取り除きます
関数型更新を使用する場合:
- 現在の状態値に依存するすべての setState
- 状態が必要な useCallback/useMemo 内
- 状態を参照するイベントハンドラー
- 状態を更新する非同期処理
直接更新しても問題ない場合:
- 状態を固定値に設定する場合:
setCount(0) - props または引数のみから状態を設定する場合:
setName(newName) - 状態が以前の値に依存しない場合
注: プロジェクトで React Compiler が有効になっている場合、コンパイラーが一部のケースを自動的に最適化できます。ただし、正確性を確保し、古いクロージャのバグを防ぐため、関数型更新の使用を引き続き推奨します。
コメント
Markdown 対応