アルパカログ

Webエンジニア兼マネージャーがプログラミングやマネジメント、読んだ本のまとめを中心に書いてます。

React コンポーネントのアンマウント時のエラーを修正する方法(componentWillUnmount)

f:id:otoyo0122:20200920181608p:plain:w300

Reactアプリで表示を切り替えるためにコンポーネントをアンマウントしたときに、下記のようなエラーが出ることがあります。

index.js:1 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 the componentWillUnmount method.

このエントリでは、Reactコンポーネントのアンマウント時のエラーを修正する方法を紹介します。

エラーの意味と解決方法

エラーの意味は、アンマウントしたコンポーネントではstateの更新が行えないため、componentWillUnmountメソッドで非同期処理やイベントの講読をキャンセルしなければメモリリークを引き起こす可能性があるというものです。

解決策としては大きく2つあります。

ひとつは、setStateを含むそれらの処理を、ReactのuseEffect副作用フック内で行うというものです。

しかし、フックには次のようなルールがあります。

  • フックを呼び出すのはトップレベルのみ
  • フックを呼び出すのは React の関数内のみ

つまり、今のところクラスコンポーネント内のメソッドからは呼べないということです。これはちょっと微妙です。

もうひとつの解決方法は、mountedのようなマウント状態を表すカスタムプロパティを定義する方法です。

流れとしては次のようになります。

  1. コンストラクタでthis.mounted = falseを定義する
  2. componentDidMount()内でthis.mounted = trueに、componentWillUnmount()内でthis.mounted = falseにする
  3. 非同期処理ではthis.mountedをチェックする

下記に例を示します。

constructor(props) {
  super(props);
  this.mounted = false;
}

componentDidMount() {
  this.mounted = true;
}

componentWillUnmount() {
  this.mounted = false;
}

doSomething() {
  // 非同期処理の前にmountedをチェックする
  this.mounted && this.setState({ ... });
}

これでエラーが発生しなくなります。

以上です。

このエントリでは、Reactコンポーネントのアンマウント時のエラーを修正する方法を紹介しました。

参考になった方は、ぜひ「はてブ」やSNSでシェアしていただけると嬉しいです。

参考ページ