📝
React Memory leak エラーの出力対策
React Memory leak メモリリーク対策
useEffect でState を扱うときの注意点
React でStateを使うとみかけるこのワーニング。
unmountsしてるけど、メモリ開放ができてないことをあらわしてます。
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.
解決案
unmount しているときはstateにアクセスさせないようにする、というのがよいみたいです。
useEffect の return 処理は unmount するときコールされるのでフラグをたてて抑制します。
useEffect(() => {
let isMounted = true; // note this flag denote mount status
someAsyncOperation().then(data => {
if (isMounted) setState(data);
})
return () => { isMounted = false }; // use effect cleanup to set flag false, if unmounted
});
もっと簡単な解決方法
useState に上記の解決案をいれたhooksがあります。
import { useStateIfMounted } from "use-state-if-mounted";
const Button = (porps Props) => {
// const [visible, setVisible] = useState(false);
const [visible, setVisible] = useStateIfMounted(false);
useState を useStateIfMounted にするだけで対応できます。
TypeScript 未対応なのが残念です。
余裕ができたら、PR してみようかと思います。
追記)React 18 からはこのエラーが廃止されるそうです。
コメントいただきました。
もともとは下記のようなマウント後に参照を持ち続けるケースを警告するためのエラーだったようです
useEffect(() => {
function handleChange() {
setState(store.getState())
}
store.subscribe(handleChange)
// この unsubscribe がない場合はリークします。
return () => store.unsubscribe(handleChange)
}, [])
ので、私が書いたケースはエラーはでるが実質的にはリークしてないようです。
sosoさんが検証されています。素晴らしいです。
ということで、 React 18にあげましょう!
Discussion
この場合はメモリリークおきないらしいですよ
有益な情報ありがとうございます。
ちょうど続編を書こうと思ったのですが、soso さんの記事、引用もしっかりしていてこちら読んだほうがいいですね。
今ちょうど同じエラー出ていたので助かりました、ありがとうございます。