React报错之无法在未挂载的组件上执行React状态更新 - chuckQu
source link: https://www.cnblogs.com/chuckQu/p/16548811.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
React报错之无法在未挂载的组件上执行React状态更新
正文从这开始~
为了解决"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
的实际值。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK