Useeffect Not Being Called And Not Updating State When Api Is Fetched
Solution 1:
The error message gives it away, Cannot read property 'current' of null
, the only place where current
is called is in weather.current
in the src
of Card.Img
, so we deduce that weather
was null
during the render.
The reason this happens is because the api call is asynchronus, it doesn't populate the state immediately, so the render happens first and tries to read .current
from the initial weather state null
.
Answer : in your render
method, make sure not to read weather.current
while weather
is null
.
You can for example use {weather && <Card>...</Card}
to hide the whole card until the data is loaded and show a loading indicator, or you can use src={weather && weather.current.condition.icon}
as a quick workaround.
constWeather = ({capital}) => {
const [weather, setWeather] = useState(null);
useEffect(() => {
console.log("useEffect called");
const getWeather = async () => {
try {
const res = await axios.get(
`http://api.apixu.com/v1/current.json?key=53d601eb03d1412c9c004840192807&q=${capital}`,
);
setWeather(res.data);
} catch (e) {
console.log(e);
}
};
getWeather();
}, [capital]);
console.log(weather);
return (
<Cardstyle={{width: "18rem", marginTop: "25px"}}><Card.Imgvariant="top"src={weather && weather.current.condition.icon} /><Card.Headerstyle={{textAlign: "center", fontSize: "25px"}}>
Weather in {capital}
</Card.Header></Card>
);
};
Solution 2:
So, I was facing a similar issue, where it seemed like useEffect
hook was not getting invoked at all. The concerned code snippet is given below:
Within my functional component, this was the sequence of the appearance of the code:
a variable
const facetFields = [];
declaration which was supposed to be set by a AJAX call from withinuseEffect
hookuseEffect
hook within which the above variable was getting set with AJAX.useEffect( ()=>{ console.log('FacetTreeView: useEffect entered'); facetFields = getFacetFieldNames(props.tabIndex); }, []);
JSX code that uses the variable.
return (<MyComponent> { facetFields.map((facetLabel, index) => { populateFacetInstances(facetLabel) }) } </Component>)
With this code, the console statement inside the hook was not printing at all. Also, I kept getting a undefined error while map
'ing the facetFields. So, it turns out that the useHook is called after the component is rendered. So, during the rendering, the variable facetFields
is undefined
.So, I fixed this by adding this line to my JSX rendering part of code:
facetFields && facetFields.map(.....
Once, I made the above change, the control started going to the hook.So, in summary, if there is any code within JSX that is being set from useEffect
hook, then its best to defer the execution of the JSX till hook execution is completed. Although, this is not mandatory, but it will make the JSX code easier to read. This can be achieved in a simple way by using a boolean state flag.
- Define the state:
const [readyForRender, setReadyForRender] = React.useState(false); 2. Set state in hook.
useEffect( ()=>{ console.log('FacetTreeView: useEffect entered'); facetFields = getFacetFieldNames(props.tabIndex); setReadyForRender(true); }, []);
- Render JSX conditionally.
if(readyForRender){ return ( { facetFields.map((facetLabel, index) => { populateFacetInstances(facetLabel) }) } ); } else{ return null; }
Solution 3:
I had the same puzzling issue one time
You can try adding a key prop on the component when it is created in the parent code
<yourcomponentkey="some_unique_value" />
This is because in most cases, when your component is reused, based on the way it is created, it may usually re-render it with some changes instead of creating it again when you reuse it, Hence the useEffect
is not going to be called. eg in SwitchRoute, loops, conditionals...
So adding a key will prevent this from happening. If it is in a loop, you need to make sure each element is unique, maybe by including the index i
in the key if you can't find any better unique key.
Post a Comment for "Useeffect Not Being Called And Not Updating State When Api Is Fetched"