using console.log()
after using reactjs useState()
hook, doesn't return the current value of this state, How can I handle this?
Here's code for the case, try to figure out what's the console log display.
import React, { useState } from "react";
import ReactDOM from "react-dom";
function Weather() {
const [weather, setWeather] = useState();
return (
<input
value={weather}
onChange={(e) => {
setWeather(e.target.value);
console.log(weather);
}}
/>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Weather />, rootElement);
The answer: They're just queues setState , and React. useState create queues for React core to update the state object of a React component. So the process to update React state is asynchronous for performance reasons. That's why changes don't feel immediate.
What does useState return? It returns a pair of values: the current state and a function that updates it. This is why we write const [count, setCount] = useState() . This is similar to this.state.count and this.setState in a class, except you get them in a pair.
PureComponent , the state update using the updater provided by useState hook is also asynchronous, and will not be reflected immediately.
We initialize our state by calling useState in our function component. useState accepts an initial state and returns two values: The current state. A function that updates the state.
useState
by default simply does one thing and one thing only, set the new state and cause a re-render of the function. It is asynchronous in nature so by default, methods running after it usually run.
From your example, on a fresh load of the page, typing 's' causes useState to change the state, but because it is asynchronous, console.log
will be called with the old state value, i.e. undefined
(since you didn't set a value. You should consider setting an initial state, if you want to)
const [weather, setWeather] = useState(''); // Set the intial state
The only way to truly read the value of the state is to use useEffect
, which is called when there is a re-render of the component. Your method simply becomes:
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';
function Weather() {
const [weather, setWeather] = useState('');
useEffect(() => console.log(weather), [weather]);
const changeValue = event => setWeather(event.target.value);
return <input value={weather} onChange={changeValue} />;
}
const rootElement = document.getElementById('root');
ReactDOM.render(<Weather />, rootElement);
When you call setWeather
, you trigger a rerender of your component, which will call again this function. However, the console.log(weather);
inside the function still references the first value returned by useState
, which is your orignal value. If you want to print it you should be doing :
console.log(e.target.value);
onChange={(e) => {
setWeather(e.target.value);
console.log(weather);
}}
when this function is fired, since setWeather
is async, it will be passed to web api. Javascript engine does not handle this function. wep api handles this and when it is done event loop which is part of the web api pass this to the call stack.
call stack is where functions get executed. once async functions are passed to the web api, regardless of its executing time (even though it has 0 second time out), they will not moved to call stack unless javascript engine finishes the execution of sync code. once call stack is free, event loop will pass the function to call stack to be executed.
So in your code, onChange()
is passed to call stack. Inside of this function, 2 functions have to be executed. since setWeather
is async, it goes to web api, gets the e.target.value
, meanwhile console.log gets executed. when there is no sync code left in the call stack, event loop pushes the setWeather to the call stack to be executed.
Let's say you enter "name" to the input field. after "nam", state is "nam", but when you type "e", this will be executed in webapi, so while it is in web api, console.log will log the current state which is "nam". that is why you will always see the console one character behind
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With