Design comparison
Solution retrospective
Hi need help figruing out why i need to click two times for api request to update, have tried alot of soulutions and if i put updater() outside a function i solve it but then the ip adress isent shown in first render
Community feedback
- @CarlHummPosted about 1 year ago
Hi
I had a look at your solution and can see what you mean by having to click twice to have the map move/details update.
I noticed the following happens.
- You click the button inside
<IPInput />
and get taken tohandleClick
- Within
handleClick
you callupdater()
which updates the ip state in the parent component (<App />
) - This state is then passed to
<DisplayValues />
component which you can see from the updated IP value. - Since we're still in an active clickEvent, we return to IPInput's
handleClick
and continue (Not re-rendered yet) - You then make a fetch request using
props.ip
as the value foripAddress=
(Still haven't re-rendered so props.ip is the same as the initial render) - After retrieving the data, you attempt to
setState
for the other fields (Same content, nothing updates) - Now that the click event is finished, we return (Component re-renders because of ip state change)
- If we click now for a second time props.ip will be the correct value and the fetch will retrieve and set the correct state for the map - but each new ip will require two clicks.
Why does this happen?
Component props are not updated till re-render, so props.ip is a stale value and you should use update instead. Not precisely sure why the component waits till the end of the click event to re-render, perhaps to do with how react asynchronously queues and batches state updates, not sure. But if it didn't wait, the fetch would be unreachable anyway.
Quick Fix to Test
- Use the input value (update) to query the ip instead of props.ip
Alternative Solutions
- Since IPInput is just there to grab the ip and set the parentState it should be dumb. Instead of adding handleClick function with code identical to the parent useEffect, you could delete this, and only pass setIp as props. Then you could change the state dependency for your useEffect to ip so that when IPInput updates, the useEffects runs.
- Or if you want more control over when fetch is called you could create a seperate fetch function (which sets state for IP) in App.js, call it initially in your useEffect and then pass the function to IPInput as a prop to call at your discretion.
Including API Keys
Other than this, I highly reccommend you
npm i dotenv --save
and create a.env
file to store your API key. Within this file you can do something likeREACT_APP_API_KEY="ASDSADSA"
and then in your app use${process.env.REACT_APP_API_KEY}
. Be sure not to upload it with the key filled for github as others can use your API key and exhaust credits.I'm still a beginner learning react so there might be inaccuracies in my explanation, hopefully you understand despite the bad formatting :)
Good luck on your challenge
Marked as helpful1 - You click the button inside
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord