I am creating a website that lists several open job positions.
I want to GET
all the job positions once the component mounts. Therefore, I used useEffect
.
I am setting the state inside useEffect
, which I think is causing the error:
Warning: Can't perform a React state update on an unmounted component.
I would like to know how I can fix this warning. I am not understanding why I cannot set the state inside useEffect
My component
function MyComponent({changeType}) {
const [user, setUser] = React.useState([]);
const [positions, setPositions] = React.useState([]);
async function getAllPositions(){
let response = await axios("http://www.localhost:3000/api/v1/positions");
setPositions(response.data)
}
useEffect( ()=> {
let jwt = window.localStorage.getItem('jwt')
let result = jwtDecode(jwt)
setUser(result)
changeType() # It is a function passing props to the parent of "MyComponent"
getAllPositions()
}, [],
)
return(
<div>
Something
</div>
)
}
You should check if component is still mounted before update state after an async call
useEffect( ()=> {
let unmounted = false
async function getAllPositions(){
let response = await axios("http://www.localhost:3000/api/v1/positions");
if(!unmounted)
setPositions(response.data)
}
let jwt = window.localStorage.getItem('jwt')
let result = jwtDecode(jwt)
setUser(result)
getAllPositions()
return () => {
unmounted = true
}
}, [])
@Alexander Vidaurre Arroyo's answer is correct. You're essentially need to ensure that state isn't being updated when the component is unmounted.
I tried rewriting his answer a little bit in the spirit of hooks to see how you can extract some of the approach of checking for if a component is mounted to determine if state should be updated.
import React, { useCallback, useRef, useState } from 'react';
const useIsMounted = () => {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => isMounted.current = false;
}, []);
return useCallback(() => isMounted.current, []);
};
const useAsyncState = (defaultValue) => {
const isMounted = useIsMounted();
const [value, setRawValue] = useState(defaultValue);
const setValue = useCallback((newValue) => {
if (isMounted()) {
setRawValue(newValue);
}
}, []);
return [value, setValue];
};
const getAllPositions = async () => {
const response = await axios("http://www.localhost:3000/api/v1/positions");
return response.data;
};
function MyComponent() {
const [user, setUser] = useAsyncState([]);
const [positions, setPositions] = useAsyncState([]);
useEffect(async () => {
const jwt = window.localStorage.getItem('jwt');
const result = jwtDecode(jwt);
setUser(result);
setPositions(await getAllPositions());
}, [setPositions, setUser]);
return(
<div>
Something
</div>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With