注释从这开始~
总览
为了解决 "Warning: Can't perform a React state update on an unmounted component"
,能够在你的useEffect
钩子中申明一个 isMounted
布尔值,用来跟踪组件是否被装置。一个组件的状态只有在该组件被挂载时才会被更新。
import {useState, useEffect} from 'react';
const App = () => {const [state, setState] = useState('');
useEffect(() => {
// 👇️ set isMounted to true
let isMounted = true;
async function fetchData() {const result = await Promise.resolve(['hello', 'world']);
// 👇️ only update state if component is mounted
if (isMounted) {setState(result);
}
}
fetchData();
return () => {
// 👇️ when component unmounts, set isMounted to false
isMounted = false;
};
}, []);
return (
<div>
<h2>State: {JSON.stringify(state)}</h2>
</div>
);
};
export default App;
当咱们试图更新一个未挂载的组件的状态时,会呈现 ” 无奈在未挂载的组件上执行 React 状态更新 ” 的正告。
isMounted
解脱该正告的含糊其辞的形式是,在 useEffect
钩子中应用 isMounted
布尔值来跟踪组件是否被挂载。
在 useEffect
中,咱们初始化 isMounted
布尔值为true
。
咱们的fetchData
函数执行一些异步的工作,最常见的是一个 API 申请,并依据响应来更新状态。
然而,须要留神的是,咱们只有当 isMounted
变量被设置为 true
时,才会更新状态。
async function fetchData() {const result = await Promise.resolve(['hello', 'world']);
// 👇️ only update state if component is mounted
if (isMounted) {setState(result);
}
}
这能够帮忙咱们防止正告,因为如果组件没有挂载,咱们就不会更新状态。
当组件卸载时,从 useEffect
钩子返回的函数会被调用。
return () => {
// 👇️ when component unmounts, set isMounted to false
isMounted = false;
};
咱们设置 isMounted
变量为 false
,示意该组件不再挂载。如果fetchData
函数在组件卸载时被调用,if
代码块不会执行是因为 isMounted
设置为false
。
async function fetchData() {const result = await Promise.resolve(['hello', 'world']);
// 👇️ only update state if component is mounted
if (isMounted) {setState(result);
}
}
提取
如果常常这样做,能够将逻辑提取到可重用的钩子中。
import {useState, useEffect, useRef} from 'react';
// 👇️ extract logic into reusable hook
function useIsMounted() {const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => {isMounted.current = false;};
});
return isMounted;
}
const App = () => {const [state, setState] = useState('');
// 👇️ use hook
const isMountedRef = useIsMounted();
useEffect(() => {async function fetchData() {const result = await Promise.resolve(['hello', 'world']);
// 👇️ only update state if component is mounted
if (isMountedRef.current) {setState(result);
}
}
fetchData();}, [isMountedRef]);
return (
<div>
<h2>State: {JSON.stringify(state)}</h2>
</div>
);
};
export default App;
useRef()
钩子能够传递一个初始值作为参数。该钩子返回一个可变的 ref 对象,其 .current
属性被初始化为传递的参数。
咱们在 useIsMounted
钩子中跟踪组件是否被挂载,就像咱们间接在组件的 useEffect
钩子中做的那样。
须要留神的是,在 fetchData
函数中,咱们必须查看 isMountedRef.current
的值,因为ref
上的 current
属性是 ref
的理论值。