Closed kawabata2018 closed 3 years ago
useEffect
を使った時のcleanupが鬼門。
componentDidMount
+ componentDidUpdate
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.
useEffect(() => {
const url = new URL(`${process.env.REACT_APP_SERVERLESS_ENDPOINT}/fetch-isbn-summary`);
const params = new URLSearchParams();
params.append("isbn", isbn);
url.search = params.toString();
setTimeout(
async () => {
const res = await fetch(url.toString());
if (res.status !== 200) {
setIsPending(false);
setIsNoData(true);
console.log("status code not 200");
return;
}
const data: Array<Book> = await res.json();
if (data.length === 0) {
setIsPending(false);
setIsNoData(true);
console.log("response data is null");
return;
}
setBook(data[0]);
setIsPending(false);
console.log("data fetched successfully!")
}, 2000
)
}, [isbn]);
マウントされていないコンポーネントの状態(React state)を更新するのは、メモリの無駄遣いだから。
あるコンポーネントで非同期タスクを走らせた後、そのコンポーネントがアンマウントされた(ページを移動するなど)ときに、余計なプロミスについては中断してあげるのが望ましいということ。
useEffect(() => {
const url = new URL(`${process.env.REACT_APP_SERVERLESS_ENDPOINT}/fetch-isbn-summary`);
const params = new URLSearchParams();
params.append("isbn", isbn);
url.search = params.toString();
const abortController = new AbortController();
setTimeout(
async () => {
try {
const res = await fetch(url.toString(), {
signal: abortController.signal
});
if (res.status !== 200) {
setIsPending(false);
setMessage("サーバから正しいステータスが返ってこなかったよ。ぴえん");
console.log("status code not 200");
return;
}
const data: Array<Book> = await res.json();
if (data.length === 0) {
setIsPending(false);
setMessage("書籍情報がなかったよ。ぴえん");
console.log("response data is null");
return;
}
setBook(data[0]);
setIsPending(false);
console.log("data fetched successfully!")
}
catch (err) {
if (err.name === 'AbortError') {
console.log("fetch aborted!");
} else {
setMessage("予期せぬエラーが出たよ。ぴえん");
console.error(`Error:\n${err.message}`);
}
}
}, 2000
)
// アンマウントされる時にabort!してfetchを強制中止する
return () => abortController.abort();
}, [isbn]);
追加の調査事項は別途issueを立てる
背景
To do
完了条件