The text starts here~
Overview
To fix "Warning: Can't perform a React state update on an unmounted component"
, declare a isMounted
boolean in your useEffect
hook to track whether the component is installed. The state of a component is only updated when the component is mounted.
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;
When we try to update the state of an unmounted component, the warning "Cannot perform React state update on unmounted component" appears.
isMounted
A straightforward way to get rid of this warning is to use isMounted
boolean in the useEffect
hook to track whether the component is mounted or not.
In useEffect
we initialize isMounted
with a boolean value of true
.
Our fetchData
function performs some asynchronous task, most commonly an API request, and updates state based on the response.
Note, however, that we only update the state when the isMounted
variable is set to true
.
async function fetchData() {
const result = await Promise.resolve(['hello', 'world']);
// 👇️ only update state if component is mounted
if (isMounted) {
setState(result);
}
}
This helps us avoid warnings because if the component isn't mounted, we don't update the state.
The function returned from the useEffect
hook will be called when the component is unmounted.
return () => {
// 👇️ when component unmounts, set isMounted to false
isMounted = false;
};
We set the isMounted
variable to false
, indicating that the component is no longer mounted. 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);
}
}
extract
If you do this frequently, you can extract the logic into reusable hooks.
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()
hook can be passed an initial value as a parameter. The hook returns a mutable ref object whose .current
property is initialized to the passed parameter.
We track whether the component is mounted in the useIsMounted
hook, just as we did directly in the component's useEffect
hook.
It should be noted that in the fetchData
function, we have to check the value of ---152f224bb6d5773b89f6a986be211eaf isMountedRef.current
, because ref
ref
the current
attribute The actual value of ref
.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。