0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

useEffectの依存配列にオブジェクトを指定して無限ループした場合の対処方法

Posted at

依存配列にオブジェクトを指定した場合のuseEffectの挙動について

Reactの使いはじめの頃、おそらく頻繁に出くわす問題にuseEffectでの無限ループ問題がある。
つまずきがちなのが、以下の例のようにオブジェクトをuseEffectの依存配列に指定した場合である。

const Component = () => {
  const [count, setCount] = useState(0);

  const hoge = {id:'xxx',name:'test'};

  useEffect(() => {
    // 無限ループする
    setCount(n => n + 1);
  }, [hoge]);

  return <div>{count}</div>;
};

ここではhogeというオブジェクトをuseEffectの依存配列に指定している。
この場合、次のような実行の流れになってしまい、無限ループが発生する。

  1. Componentのレンダリングする。このときhogeオブジェクトを生成。
  2. useEffectの実行
  3. countの状態を+1する
  4. countの状態がComponentを再レンダリング。このときhogeオブジェクトを生成。
  5. hogeオブジェクトの参照先が変更されたのでuseEffectを再実行
  6. 以降、3から5を繰り返す

このようにhogeオブジェクトがレンダリングのたびに生成されてしまうため、hogeオブジェクトの参照先が変更されてしまい、無限ループが発生する。

問題の対処

この問題を回避する方法はいくつかあるが一番簡単な回避方法は依存配列にオブジェクトではなく、オプジェクトのプロパティを指定する方法である。

const Component = () => {
  const [count, setCount] = useState(0);

  const hoge = {id:'xxx',name:'test'};

  useEffect(() => {
    setCount(n => n + 1);
  }, [hoge.id]); // 依存配列にhogeオブジェクトのidプロパティを指定。

  return <div>{count}</div>;
};

このようにオブジェクトのプロパティを指定しておくとhoge.idのプロパティの値が前のレンダリングの値と変わらない限り、useEffectは実行されない。useEffectの依存配列にオブジェクトを指定して無限ループに陥ってしまった場合の対策方法の参考までに。

補足

もう一つの回避方法としてuseMemoを利用する方法もあるがこの文章では割愛

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?