89
64

More than 3 years have passed since last update.

ReactでUnmountしたときにstateをメモリリークしない便利関数

Last updated at Posted at 2020-05-04

Reactでアプリケーション開発を行う際、useStateを使ってcomponentを生成する場合はそのcomponentがUnmount(画面でそのcomponentを使用しなくなったとき)したとき、stateをメモリリークしないようにしないと宜しくないですよね。
実際、開発ツールでもconsoleでwarning表示されます。

Warning: 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.

ではUnmountしたときにstateをメモリリークしない書き方について。

classComponentとhooksの書き方

いまのReactのバージョンで開発する際はhooksで構築するかと思います。
その場合、Unmount時に行う処理はuseEffectを使用してそのなかで実装します。

useEffect(() => {
  return () => {
    // Unmount時の処理を記述
  };
}, []);

classComponentのときはライフサイクルメソッドの「componentWillUnmount」内で記述します。

componentWillUnmount() {
  // Unmount時の処理を記述
}

stateを解放させる便利関数

ここからはhooksで開発する前提で話を進めていきます。
先ほど説明したComponentごとのuseEffect内にUnmout時にstateをメモリーリークしない記述をしていくのでもいいのですが、大規模な開発になっていくつものComponentに同じような記述をしていくとそれはそれで面倒になってきます。
なので、helper関数を作って処理を簡素化させるのが宜しいかと思われます。

あらゆる書き換え可能な値を保持しておくのに便利なhook「useRef」を使います。
この関数でUnmount時にunmountRef.currentがtrueになります。

useUnmountRef関数
const useUnmountRef = () => {
  const unmountRef = useRef(false);

  useEffect(
    () => () => {
      unmountRef.current = true;
    },
    []
  );

  return unmountRef;
};

そのuseUnmountRefとuseStateを融合させたhelper関数を作ります。

useSafeState
const useSafeState = (unmountRef, defaultValue) => {
  const [state, changeState] = useState(defaultValue);
  const wrapChangeState = useCallback(
    (v: any) => {
      if (!unmountRef.current) {
        changeState(v);
      }
    },
    [changeState, unmountRef]
  );

  return [state, wrapChangeState];
};

Unmountしてないときだけstateが書き換えられるようにしています。

Component内で実装

Hoge.jsx
const unmountRef = useUnmountRef();
const [state, setState] = useSafeState(unmountRef, {stateの初期値});

これだけで済みます。
なんとも便利な関数ですね。

また、Unmount時の処理はこの書き方になります。

if (unmountRef.current) {
 // Unmount時の処理
}

たとえばblob画像を生成して、その画像を解放させるときrevokeObjectURL()関数を使いますが、その箇所に記述すると宜しいかと思われます。

89
64
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
89
64