yn2011's blog

技術メモ

Can't perform a React state update on an unmounted component... エラーにConetextが原因でハマった話

環境

  • react 16.8.6

事象

React.useEffectを使用しているコンポーネントContext.Provider配下に配置したところ以下のエラーが発生した。

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function

コード例は省略するが、上記のエラー発生時にReact.useEffect内でAPIコール、その結果をsetState等すると何故かuseEffectの処理が無限ループする。

原因

本来はfunctional componentの外側でContextを定義するべきだが、以下のようにfunctional componentの内側で定義していた。

export const HogeContextProvider = (props: HogeProps) => {
  const HogeContext = React.createContext(null);
  return (...

以下が正しい。

export const HogeContext = React.createContext(null);

export const HogeContextProvider = (props: HogeProps) => {
  return (
      <HogeContext.Provider value={hoge}>
        {props.children}
      </HogeContext.Provider>
  );

functional componentの内側は、stateの更新等で何度もコールされるのでその度にContextを再作成していたことが原因の模様。

最初はContextをProvider配下でReact.useContextしていないことが原因かなと思って調べたら、そもそもContextをexportしていないことに気づいて、定義位置の間違いに思い当たった。

反省

DOMがstateに対応して更新されることは当然だが、functional componentの内部の処理が何度もコールされるイメージがなかった。どういうときにコールされるのか整理したい。

React、こういう単純なミスの原因特定が難しくてハマると解決に1,2時間ぐらいは必要になってしまうこともあり辛さがある。