Closed2

Reactの公式ドキュメント読む!

KeiKei

useState

https://react.dev/reference/react/useState

useStateについて少し気になったところをまとめる。。。

Usage

  1. コンポーネントにstateを追加する
const [state, setState] = useState(initialState);
  1. 以前のstateに応じて、状態更新する(以下参考↓)
参考
// state宣言
const [age, setAge] = useState(42);

// 🙅set関数を実行しても、すでに実行中のageが更新されない
function handleClick() {
  setAge(age + 1); // setAge(42 + 1)
  setAge(age + 1); // setAge(42 + 1)
  setAge(age + 1); // setAge(42 + 1)
}

// 🙆set関数の引数にコールバック関数を渡す
function handleClick() {
  setAge(a => a + 1); // setAge(42 => 43)
  setAge(a => a + 1); // setAge(43 => 44)
  setAge(a => a + 1); // setAge(44 => 45)
}

ただし、必ず関数を渡さないといけないわけではないっぽい?

  1. オブジェクトや配列の状態を更新する
    reactではstateは読み取り専用なので、mutate(変異)ではなくreplace(置換)する必要がある

参考
オブジェクト → https://react.dev/learn/updating-objects-in-state
配列 → https://react.dev/learn/updating-arrays-in-state

// 🚩 既存オブジェクトをmutateしてはいけない
form.firstName = 'Taylor';

// ✅ 新しいオブジェクトでreplaceする
setForm({...form,  firstName: 'Taylor' });

useImmerというライブラリを使用すればオブジェクトをミュータブル的に更新する書き方ができる。
(内部的にイミュータブルな更新が行われているので問題ない)
https://github.com/immerjs/use-immer

トラブルシューティング

I’m getting an error: “Too many re-renders”

このエラーは無限レンダリングが起こっている。以下参考。

// 🚩 Wrong: レンダリング中にハンドラを呼んではいけない
return <button onClick={handleClick()}>Click me</button>

// ✅ Correct: passes down the event handler
return <button onClick={handleClick}>Click me</button>

// ✅ Correct: passes down an inline function
return <button onClick={(e) => handleClick(e)}>Click me</button>

ステートを関数に設定しようとしているが、代わりに呼び出される

const [fn, setFn] = useState(someFunction);

function handleClick() {
  setFn(someOtherFunction);
}

ReactはsomeFunctionがイニシャライザー関数、someOtherFunctionがアップデータ関数であると仮定し、それらを呼び出して結果を保存しようとします。実際に関数を格納するためには、両方のケースでそれらの前に() =>を置く必要があります。

// 正しい例
const [fn, setFn] = useState(() => someFunction);

function handleClick() {
  setFn(() => someOtherFunction);
}
このスクラップは2024/03/30にクローズされました