The setState
is asynchronous
This is the expected behavior.
Calls to setState
are asynchronous, React seeks to perform a batch update (batch) to cause less rendering. That answer talks a little about batch updates (batches).
In view of this behavior of setState
, you will be able to accomplish a console.log
state updated only in the next rendering, and not just below the setState
.
Citing the documentation:
Why setState is giving me the wrong value?
Calls to setState are asynchronous - don’t trust this.state to reflect the new value immediately after calling setState. (...)
When setState is asynchronous?
Currently, setState is asynchronous within event handlers.
This ensures that, for example, both Parent
how much Child
flame setState
after a click event, Child
is not rendered twice. Instead, React performs all status updates at the end of the browser event. This results in a significant performance improvement for larger applications.
This is an implementation detail, so avoid depending on it directly. In future versions, React will do batch updates in more cases.
A practical example:
function Exemplo() {
const [state, setState] = React.useState('primeiro render');
React.useEffect(() => {
setState('segundo render');
console.log('useEffect após setState:', state);
}, []);
console.log('RENDER:', state);
return <div>Estado: {state}</div>
}
ReactDOM.render(<Exemplo />, document.querySelector("#container"));
<div id="container"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
The difference between an object and a function in the setState
A specific detail about your case setDados(dados => productInfo)
: there is a difference between using an object and a function in the setState
. As your new state is independent of the current state, you can simply use setDados(productInfo)
.
As documented:
Passing an update function allows you to access the current value of state
within it. Like the calls from setState
are done in batches, this allows you to chain updates and ensure that they compose rather than conflict.
Below is an example with setTimeout
500ms to simulate a situation where this conflict happens. Click several times quickly on the same button to update the status then see the difference between the two modes:
function Exemplo() {
const [stateUm, setStateUm] = React.useState(0);
const [stateDois, setStateDois] = React.useState(0);
function updateUm() {
setTimeout(() => setStateUm(stateUm + 1), 500);
}
function updateDois() {
setTimeout(() => setStateDois(val => val + 1), 500);
}
return (
<div>
<div>
<p>stateUm: {stateUm}</p>
<button onClick={updateUm}>setStateUm(stateUm + 1)</button>
</div>
<div>
<p>stateDois: {stateDois}</p>
<button onClick={updateDois}>setStateDois(val => val + 1)</button>
</div>
</div>
);
}
ReactDOM.render(<Exemplo />, document.querySelector("#container"));
<div id="container"></div>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
@Rafaeltavares then, it turns out I need to use the method toLocaleString to format the product price to BRL. But as the object, at the first click, is empty, React returns an error stating that the value price within the commodity is Undefined and therefore fails to execute the toLocaleString. In short, I need you to setDados be updated BEFORE the information appears on the screen. But I’m not finding the correct logic.
– Ricardo Passos
To debug, I think it would be better to give: console.log(productInfo);
– Marcos ACR
@Ricardosteps you need to update the value so that the
dados
is formatted? You can format theproductInfo
before putting in thesetDados
...– Rafael Tavares
@Rafaeltavares his comments + the answer managed to give me a light. I managed to solve the problem. Thank you very much <3.
– Ricardo Passos
Try to use this way:

setDados(dados => {...dados, ...productInfo});

– Lucas Moreno