Reputation: 11
I have just started learning reactjs. I am trying to set the state with an object received from the API, and then display the results from the state. When I try to display the results, it shows state object undefined. When I query the API for a second time, it sets the state to the object received from API.
const SearchByName = () => {
const [recipes, setRecipes] = useState({
recipesObj: {},
loding: false,
});
const fetchData = async () => {
try {
setRecipes({ loading: true });
const res = await axios.get(`url_to_API`);
console.log(res.data) // prints returned object from API
setRecipes({ recipesObj: res.data, loading: false });
console.log(recipes.recipesObj); // empty object
} catch (err) {
console.error(err);
}
};
};
const onSubmit = (e) => {
e.preventDefault();
fetchData();
setSearchStr('');
};
Upvotes: 0
Views: 72
Reputation: 8586
In react we have lifecycle components your code is correct but what missing is useEffect for functional components
import {useEffect, useState } from "react"
const SearchByName = () => {
const [recipes, setRecipes] = useState({
recipesObj: {},
loding: false,
});
useEffect(()=>{
// useEffect can access fetchData anytime
fetchData()
},[])
const fetchData = async () => {
try {
setRecipes({ loading: true });
const res = await axios.get(`url_to_API`);
console.log(res.data) // prints returned object from API
setRecipes({ recipesObj: res.data, loading: false });
console.log(recipes.recipesObj);
} catch (err) {
console.error(err);
}
};
};
It should work now, the only difference is the useEffect lifecycle hook
Upvotes: 0
Reputation: 196
Remember set state in react is and Async function
To know more about what is state in react please check this Llink in react docs .
React state in both functional and class based is an async function, to handle what you want you should check your state in an useEffect or outside of that related function that setState fired.
const SomeComponent = () => {
const [dataFetched,setDataFetched] = React.useState(false);
const mockTheRequest = () => {
// make the request and set the state
setDataFetched(true)
}
React.useEffect(()=>{
// fire your xhr request when component rendered.
mockTheRequest()
},[])
React.useEffect(() => {
if(dataFetched){
// on data fetched
console.log("state", dataFetched)
}
},[dataFetched])
return(
<div>
<span>
is data fetched? {dataFetched}
</span>
</div>
)
}
Upvotes: 0
Reputation: 4480
You're replacing the state with { loading: true }
, here recipes.recipesObj
will become undefined. you need to prepend the earlier state. Try changing like this or you can use different state
to manage the loading and data
const fetchData = async () => {
try {
setRecipes({ ...recipes, loading: true }); // Here was the problem
or setRecipes({ recipesObj: {}, loading: true });
const res = await axios.get(`url_to_API`);
console.log(res.data) // prints returned object from API
setRecipes({ recipesObj: res.data, loading: false });
console.log(recipes.recipesObj);
} catch (err) {
console.error(err);
}
};
};
Upvotes: 1