Reputation: 292
I am using React hooks and I need to store the data from my server which is an object, to a state.
This is my state:
const [sendingTime,setSendingTime] = useState({})
This is how I set it inside useEffect:
const getTime= () =>{
axios.get("https://localhost:1999/api/getLastUpdatedTime")
.then(res => {
console.log(res.data)
setSendingTime({sendingTime : res.data})
console.log('sendingTime is coimng',sendingTime)
})
.catch(err => console.error(err))
}
useEffect(() => {
getCount()
getTime()
},[])
Now when I console.log the object state it returns an empty object. Although if I set the object to any variable and then console.log it it doesn't return an empty object. But both ways I am unable to access the properties of the object.
This is what I was doing previously:
const[time,setTime] = useState({
totalComplaintsTime: '00:00',
resolvedComplaintsTime: '00:00',
unresolvedComplaintsTime:'00:00',
assignedComplaintsTime:'00:00',
supervisorsTime:'00:00',
rejectedComplaintsTime:'00:00'
})
const getTime= () =>{
axios.get("https://localhost:1999/api/getLastUpdatedTime")
.then(res => {
console.log(res.data)
setTime({
totalComplaintsTime: res.data.Complaints[0].updatedAt,
resolvedComplaintsTime: res.data.Resolved[0].updatedAt,
unresolvedComplaintsTime: res.data.Unresolved[0].updatedAt ,
assignedComplaintsTime: res.data.Assigned[0].updatedAt ,
rejectedComplaintsTime: res.data.Rejected[0].updatedAt,
supervisorsTime: res.data.Supervisors[0].updatedAt
})
})
.catch(err => console.error(err))
}
useEffect(() => {
getCount()
// getTime()
getTime()
},[])
And this is how I used the states to set the dynamic values :
Last updated at {time.resolvedComplaintsTime}
This is working perfectly fine but I wanted to store the data in an object state and then access it, which would've been easier and more efficient. Also I wanted to pass this object to another component. That is why I wanted to make a state and store the data in that state.
So the main problem was accessing the data throughout the component. This is the solution:
sendingTime is being initialized but only when a render occurs. So we add a piece of code to check if that state is initialized or not.
This is where I wanted to display the data.
<div key={sendingTime.length} className={classes.stats}>
<UpdateIcon fontSize={"small"} /> Last updated at{" "}
{Object.keys(sendingTime).length > 0 &&
sendingTime.Complaints[0].updatedAt}
</div>
This way I can access the properties of the object stored in the sendingTime state very easily.
Upvotes: 0
Views: 91
Reputation: 4522
The other answers are correct, setState is asynchronous so you will only be able to get sendingTime
's new value on the next re-render. And as @Enchew mentions, you probably don't want to set an object as that value most likely.
Try this instead:
const [data, setData] = useState(undefined)
const getTime = () => {
axios.get("https://localhost:1999/api/getLastUpdatedTime")
.then(({ data }) => {
console.log(data)
setData(data)
})
.catch(err => console.error(err))
}
useEffect(() => {
getCount()
getTime()
}, [])
if (!data) return <p>No data...</p>
return (
<>
<p>Complaints: {data.Complaints[0].updatedAt}<p>
<p>Resolved: {data.Resolved[0].updatedAt}<p>
<p>{/* ...etc... */}</p>
</>
)
You should see the value you're expecting to see in the console.log because you're using the locally scoped variable, not the asynchronous value, which will only be updated on the next re-render.
Upvotes: 1
Reputation: 1001
setSendingTime
works asynchronously and your object may have not been saved in the state yet. Also pay attention to the way you save the time in your state, you are wrapping the result of the data in another object with property sendingTime
, which will result in the following object: sendingTime = { sendingTime: {/*data here */} }
. If you are running for sendingTime: {/*data here */}
try the following:
const getTime = () => {
axios
.get('https://localhost:1999/api/getLastUpdatedTime')
.then((res) => {
console.log(res.data);
setSendingTime(res.data);
console.log('sendingTime is coimng', sendingTime);
})
.catch((err) => console.error(err));
};
Also have a look at this - how to use hooks with a callback: https://www.robinwieruch.de/react-usestate-callback
Upvotes: 0
Reputation: 3274
setSendingTime
comes from a useState
so it is asynchronous:
When you call:
setSendingTime({sendingTime : res.data})
console.log('sendingTime is coimng',sendingTime)
The state sendTime
has not been updated, so it display the init value which is {}
Upvotes: 1