🐙

useState の引数に関数を渡す時は記述で挙動が変わる件 | Lazy initial state

2023/01/04に公開

Reactの useState の引数に初期値として関数を渡してあげる場合に、ちょっとした関数の記述の違いで挙動が変わってくるので、パターン別に解説していきたいと思います。

先に結論から述べた方がわかりやすいと思うので、以下にコードを記載します。

const someExpensiveComputation = (() => {
  console.log('some expensive computation!');
  return props.count + 100;
});

// 1. 丸括弧()有りで渡した場合
// 引数に関数が渡され、レンダリングの度に実行する
const [count, setCount] = useState(someExpensiveComputation());

// 2. 丸括弧()無しで渡した場合
// 引数に関数の戻り値が初期値として渡され、初回レンダリング時のみ関数を実行する
const [count, setCount] = useState(someExpensiveComputation);

実行結果を見てみましょう。

1の「丸括弧()有り」で引数に渡してあげた場合、再レンダリングの度にコンソールに文字列が表示されます。つまり引数に関数そのものを渡しており、レンダリングのたびにその関数内の処理が行われていることが分かります。

2の「丸括弧()無し」で引数に渡してあげた場合、初回のみコンソールに文字列が表示されますが、レンダリングの度には表示されていません。

2のような挙動のことを Lazy initial state(state の遅延初期化)と呼びます。

The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded. If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render:

また、関数でラップしても 遅延初期化できます。公式のDocではこちらの方法で記載されています。

const [count, setCount] = useState(() => someExpensiveCode());

useStateの引数に関数を渡す状況がよくあるとは思いませんが、このような記述方法を覚えておいて損はないなと思いました。

Discussion