mcpField
R
rerender-functional-setstate

rerender-functional-setstate

github.com/theorcdev開発2.1k35 回インストール2 日前に更新
リポジトリ

rerender-functional-setstate について

React 開発者向けのコーディングスキルです。現在の state に依存する更新では関数形式の `setState` を推奨します。古いクロージャを防ぎ、依存関係を減らしてコールバックを安定させる方法を説明します。

主な機能

  1. 01最新の state 値に基づく更新
  2. 02古いクロージャの防止
  3. 03コールバックの安定化
  4. 04Hook の依存関係の削減

活用シーン

  1. 01state 配列への項目追加
  2. 02コールバック内での state 更新
  3. 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} />
}

メリット:

  1. 安定したコールバック参照 - 状態が変わってもコールバックを再作成する必要がありません
  2. 古いクロージャなし - 常に最新の状態値を使用します
  3. 依存関係の削減 - 依存配列を簡潔にし、メモリリークを減らします
  4. バグの防止 - React のクロージャに関する最も一般的なバグの原因を取り除きます

関数型更新を使用する場合:

  • 現在の状態値に依存するすべての setState
  • 状態が必要な useCallback/useMemo 内
  • 状態を参照するイベントハンドラー
  • 状態を更新する非同期処理

直接更新しても問題ない場合:

  • 状態を固定値に設定する場合:setCount(0)
  • props または引数のみから状態を設定する場合:setName(newName)
  • 状態が以前の値に依存しない場合

注: プロジェクトで React Compiler が有効になっている場合、コンパイラーが一部のケースを自動的に最適化できます。ただし、正確性を確保し、古いクロージャのバグを防ぐため、関数型更新の使用を引き続き推奨します。

コメント