I think it doesn’t matter whether “…reflecting a change immediately” or not.
What matters at the end, the users array is like below, consist only one name: Mosh, even though we call setUsers() TWICE
I put some console.log() in the code and the output:
Note: The source code is only one, in App.tsx, no others. So just copy all the code in App.tsx and npm install axios then the App can run properly well on the browser.
you see that the users data “after calling 1st setUsers()”, total = 11. means that “name: Mosh” is successfully added to users array and users array has 11 names.
see that the users data “before calling 2nd setUsers()”, users = 10. how come ? it supposed to be 11 right ?
Thank you very much for your help in teaching me /\
Hi, from what I know so far…at the second call ‘users’ has the same old 10 items…because the render is in progress yet, I found this in official react docs, check it.
I believe the difference is because the value of users in the addUser function is a copy of the actual value (which only changes when the function gets redeclared in the next render).
I’d suggest that you not worry about this thing for now, maybe you should note it and try exploring it once you’ve completed the course. You will need to understand when and how re-rending happens in React.
Last, but not the least, this is an excellent question. I’ve been working in React JS/Native for 2 years but never saw it this way. I guess I now know why we need to put the dependency array when using the useCallback() hook.
Note to self:
const [username, setUsername] = useState("");
const myCallback = useCallback(() => {
// username will always have the latest value
// because it's declared in the dependency array
}, [username])
I had this same question and made a post asking about it. Someone mentioned a closure and from what I was able to research on my own it sounds like a few things are combining to create this behavior: stale closures and the fact that React bundles state updates.
What I think is happening is the first call to setUsers works fine, however since React bundles state updates and doesn’t make the change right away the users list isn’t updated immediately. Meanwhile, when we make the network call using axios, we are creating a closure, which is an inner function that has references to the variables it needs that exist outside of it. The then function of our axios call forms a closure and since it is calling setState and referencing the users list, it maintains a (separate) reference to that list for itself to use. This list doesn’t include ‘Mosh’ because React hasn’t run the state updates from the first call to setState yet.
As the code continues, React gets around to calling the first setState and it updates the users list by adding ‘Mosh’ to it. However, when the network call finishes and goes to the then function, the call to setUsers is referencing a (stale) version of the users list which does not include the ‘Mosh’ user.
So the UI updates and shows ‘Mosh’ right away because the first setState happens first whenever React gets around to calling it. But when the network call returns and adds ‘Mosh’ to the list, the user list that the closure is referencing is the one from before the first call to setState, so it’s as if the first one never happened, which is why you only see one ‘Mosh’ user.
I’m not sure if @Mosh purposely intended to use React in this way. Seems a bit funky to be using side effects of stale closures and React bundling state updates, but it works. I think it would have helped to explain this a bit more in the videos but closures are a bit more of an advanced topic I think.