[解決済み] componentWillUnmountで取得をキャンセルする方法
質問
タイトルにある通りだと思います。取得中のコンポーネントをアンマウントするたびに、黄色い警告が表示されます。
コンソール警告 を呼び出すことができません。
setState
(またはforceUpdate
) をアンマウントされたコンポーネントの上に置くことができます。これは仕方がないことですが、、、。修正するには、サブスクリプションと非同期タスクをすべてキャンセルしてcomponentWillUnmount
メソッドですべてのサブスクリプションと非同期タスクをキャンセルします。
constructor(props){
super(props);
this.state = {
isLoading: true,
dataSource: [{
name: 'loading...',
id: 'loading',
}]
}
}
componentDidMount(){
return fetch('LINK HERE')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
どのように解決するのですか?
Promise を実行すると、それが解決されるまでに数秒かかることがあり、その間にユーザーはアプリ内の別の場所に移動しているかもしれません。そのため、Promiseが解決されるときに
setState
はマウントされていないコンポーネントで実行され、エラーが発生します。また、メモリリークも発生する可能性があります。
そういうわけで、非同期ロジックの一部をコンポーネントの外に出すのがベストなのです。
そうでない場合は、何らかの方法で プロミスをキャンセルする . あるいは、最後の手段として(アンチパターンですが)、コンポーネントがまだマウントされているかどうかをチェックするための変数を保持することができます。
componentDidMount(){
this.mounted = true;
this.props.fetchData().then((response) => {
if(this.mounted) {
this.setState({ data: response })
}
})
}
componentWillUnmount(){
this.mounted = false;
}
もう一度強調しておきますが、この
はアンチパターンです。
で十分なのですが、あなたの場合、この
Formik
の実装と同じです)。
に関する同様の議論は GitHub
EDITです。
これはおそらく、同じ問題(React以外何も持っていない)を解決するために フック :
OPTION A:
import React, { useState, useEffect } from "react";
export default function Page() {
const value = usePromise("https://something.com/api/");
return (
<p>{value ? value : "fetching data..."}</p>
);
}
function usePromise(url) {
const [value, setState] = useState(null);
useEffect(() => {
let isMounted = true; // track whether component is mounted
request.get(url)
.then(result => {
if (isMounted) {
setState(result);
}
});
return () => {
// clean up
isMounted = false;
};
}, []); // only on "didMount"
return value;
}
オプションBです。
または
useRef
これはクラスの静的プロパティのように振る舞い、値が変更されてもコンポーネントを再レンダリングさせないことを意味します。
function usePromise2(url) {
const isMounted = React.useRef(true)
const [value, setState] = useState(null);
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
useEffect(() => {
request.get(url)
.then(result => {
if (isMounted.current) {
setState(result);
}
});
}, []);
return value;
}
// or extract it to custom hook:
function useIsMounted() {
const isMounted = React.useRef(true)
useEffect(() => {
return () => {
isMounted.current = false;
};
}, []);
return isMounted; // returning "isMounted.current" wouldn't work because we would return unmutable primitive
}
関連
-
[解決済み】React 17で動作するEnzymeアダプターはどれですか?
-
[解決済み] React テキストを挟んだ横長の仕切りを作る
-
[解決済み] react - createMuiThemeとcreateThemeの違い。
-
[解決済み] 非必須項目に対するYupバリデーション
-
[解決済み] Webpack のコンパイルに失敗した
-
[解決済み] reactstrapのドロップダウンで選択されたアイテムを設定する方法は?
-
[解決済み] eslint: no-case-declaration - case ブロックで予期しない字句の宣言があった。
-
[解決済み] React Hooksの「exhaustive-deps」lintルールを理解する
-
[解決済み] Reactプロジェクトに.envファイルを追加する
-
[解決済み] React JSXのforEach()でHTMLが出力されない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】React - 式は1つの親要素を持つ必要がありますか?
-
[解決済み】Reactコンポーネント内でswitchステートメントを使用するには?
-
[解決済み] テスト
-
[解決済み] ReactJS giving error Uncaught TypeError: Super expression は null か関数でなければならず、undefined ではありません。
-
[解決済み] MUI Boxは何のためのコンポーネントですか?
-
[解決済み] react router dom v4でwebpack dev serverを構成する方法は?
-
[解決済み] React - _this2.SetStateは関数ではありません。
-
[解決済み] React TypeScriptで作業しているときに、Jestが予期しないトークンに遭遇した
-
React はエラー TypeError を報告します。未定義のプロパティ 'XX' を読み取ることができない、問題は解決されました。
-
[解決済み] Reactでグローバル変数を宣言する方法とは?