(ソリューションへのジャンプ|コード|デモ)「マウントされていないコンポーネントで反応状態の更新を実行できません」という警告が表示される状況はいくつかあります。コンポーネントをアンマウントした後でも、コードのどこかで関数を使用setState
またはuseState
フックしていることは確かです。
問題は、なぜこの警告が表示されるのかということではありません。そうでなければ、適切に対処する方法を知る必要があります。ただし、警告の理由の1つは、内部の状態を更新すること、setTimeout
またはsetInterval
関数が特定の期間の後に非同期で呼び出されることです。コンポーネントのアンマウント中にタイムアウトまたは間隔をクリアしないと、関数が実行され、更新できるコンポーネントがなくなります。
この警告が表示されるもう1つの理由は、アンマウント中にサブスクライブを解除せずに非同期API呼び出しを使用することです。
解決
私たちの問題の解決策は、コンポーネントがマウント解除された後の状態の更新を防ぐことです。
しかし、コンポーネントがマウント解除されているかどうかをどのように知ることができますか?
Reactはこれらに2つのソリューションを提供します–
- クラスベースのコンポーネントで
componentWillUnmount()
は、コンポーネントをアンマウントする直前に呼び出されます。 - 関数型コンポーネントでは、
useEffect()
フックで無名関数を返します。この無名関数は、新しいレンダリングサイクルの前に呼び出されます。だから私たちはそこですべてのアンマウント作業を行います。
警告を防ぐための手順
-
var isMountedVal = 1
コンストラクターで変数を定義します。 - コンポーネント内のすべての状態更新を実行する関数を宣言します。呼び出す前に
setState
、の値isMountedVal
が1であるかどうかを確認してください。 - に設定
isMountedVal = 0
しcomponentWillUnmount
ます。
コード例
クラスベースのコンポーネント–
import React from 'react'
export default class App extends React.Component{
constructor(props){
super(props);
this.isMountedVal = 0;
this.state = {count: 1};
}
componentDidMount(){
this.isMountedVal = 1;
}
componentWillUnmount(){
this.isMountedVal = 0;
}
updateState = (stateObj) => {
if(this.isMountedVal){
this.setState(stateObj);
}
}
render(){
return(
<div>
<p>Count: {this.state.count}</p>
<p><button onClick={() => this.updateState({count: this.state.count + 1})}>Increase Count by 1</button></p>
</div>
);
}
}
React JSXコピー
機能コンポーネント–
import React, {useState, useEffect, useRef} from 'react'
export default App(){
const [count, setCount] = useState(1);
const isMountedVal = useRef(1);
useEffect(() => {
isMountedVal.current = 1;
return () => {isMountedVal.current = 0;};
})
const updateState = (callback) => {
if(isMountedVal.current){
callback();
}
}
return(
<div>
<p>Count: {count}</p>
<p><button onClick={() => updateState(() => setCount(count + 1))}>Increase Count by 1</button></p>
</div>
);
}
React JSXコピー