The useState set method is not reflecting a change immediately
Much like .setState()
in class components created by extending React.Component
or React.PureComponent
, the state update using the updater provided by useState
hook is also asynchronous, and will not be reflected immediately.
Also, the main issue here is not just the asynchronous nature but the fact that state values are used by functions based on their current closures, and state updates will reflect in the next re-render by which the existing closures are not affected, but new ones are created. Now in the current state, the values within hooks are obtained by existing closures, and when a re-render happens, the closures are updated based on whether the function is recreated again or not.
Even if you add a setTimeout
the function, though the timeout will run after some time by which the re-render would have happened, the setTimeout
will still use the value from its previous closure and not the updated one.
setMovies(result);
console.log(movies) // movies here will not be updated
If you want to perform an action on state update, you need to use the useEffect
hook, much like using componentDidUpdate
in class components since the setter returned by useState
doesn't have a callback pattern
useEffect(() => {
// action on update of movies
}, [movies]);
As far as the syntax to update state is concerned, setMovies(result)
will replace the previous movies
value in the state with those available from the async request.
However, if you want to merge the response with the previously existing values, you must use the callback syntax of state updation along with the correct use of spread syntax like
setMovies(prevMovies => ([...prevMovies, ...result]));
useState Object not updating properly
You should update the state value in the following way:
setStatedata(state=> ({
...state,
property2: '65554'
}));
In addition, you can use a custom hook from my lib that implements a deep state manager (Live Demo):
import React from "react";
import { useAsyncDeepState } from "use-async-effect2";
function TestComponent(props) {
const [state, setState] = useAsyncDeepState({
x: 123,
y: 456
});
const incX = () => {
setState(({ x }) => ({ x: x + 1 }));
};
const incY = () => {
setState(({ y }) => ({ y: y + 1 }));
};
return (
<div className="component">
<div className="caption">useAsyncDeepState demo</div>
<div>state.x : {state.x}</div>
<div>state.y : {state.y}</div>
<button onClick={() => incX()}>Inc X</button>
<button onClick={() => incY()}>Inc Y</button>
</div>
);
}
If using in the context of async code and you need to wait for updates Live Demo
import React, { useCallback, useEffect } from "react";
import { useAsyncDeepState } from "use-async-effect2";
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
function TestComponent(props) {
const [state, setState] = useAsyncDeepState({
counter: 0,
computedCounter: 0
});
useEffect(() => {
setState(({ counter }) => ({
computedCounter: counter * 2
}));
}, [state.counter]);
const inc = useCallback(() => {
(async () => {
await delay(1000);
await setState(({ counter }) => ({ counter: counter + 1 }));
console.log("computedCounter=", state.computedCounter);
})();
});
return (<button onClick={inc}>Inc</button>);
}
React useState not updating on first click
as state updates are async, you may see your state value updating by adding building to a useEffect dependency, thus causing it to fire whenever the value of building changes.
const [building, setBuilding] = useState(0);
useEffect(() => {
console.log(building);
}, [building]);
return (
<button
title="tester"
onClick={() => {
setBuilding(1);
}}
>
test
</button>
);
useState Hook not updating properly
While you could use a callback instead, eg:
setError(error => ({ ...error, empty: "no empty values" }));
I think setting the state once would make a bit more sense. If a test doesn't generate an error, set the associated property to the empty string:
setError({
length: email === "" || password === "" ? 'no lengthy values' : '',
empty: email.length < 3 ? 'no empty values' : ''
});
Even better, separate out the different states:
const [emptyError, setEmptyError] = useState('');
and then, eg, call setEmptyError
instead when you need to set the error for empty
.
Why my usestate hook value is not updating after onClick event with no error at all?
Your submit function should be like that:
const onSubmit = (e) => {
e.preventDefault();
const trans = {
text: item,
amount: amount,
id: Math.floor(Math.random() * 1000)
};
setTransaction([
...transaction,
trans
]);
setItem("");
setAmount("");
Math.sign(trans.amount) === 1
? setIncome(trans.amount)
: setExpense(trans.amount)
};
The idea is that you don't need to call setIncome/setExpense
for all existing transactions, only for the new one.
P.S. Another thing to improve is to update transactions like this:
setTransaction((prevTransactions) => [...prevTransactions, trans]);
In this case everything will work smooth. More here
React:- useState Hook value not updating for dictionary and array
State updates in React are batched into one asynchronous update. The motivation for this behavior is the fact that state change triggers a re-render, which is an expensive operation for React's virtual DOM.
Therefore, if you set state and then immediately print it, the change still won't be reflected. Only after the next render it will be reflected.
You can read more about it in this article.
Why useState is not updating immediately after button click?
In react, updating state is asynchronous. Updated value is only available during the next render. Meaning, updating & them immediately console logging will give you the old state.
setTest(true);
console.log(test); //test is still false
You can print the state value to see the update -
return(
<>
<button onClick={fun}>Test</button>
{test}
</>
}
React hook useState not updating onclick
React batches the state update. If you will check the state update immediately after updating the state react then you may not get the updated state. You can check the updated state in render method. It should be updated there.
Related Topics
How to Increment a Number After Every 1 Second Using JavaScript
Connection Refused! Is Selenium Server Started
React Use State to Show Otherwise Hide
Postman Test - Validating String Values in an Object in an Array
How to Resolve Position:Fixed for a Bottom Toolbar on iOS (Iphone/Ipad)
How to Convert Postgresql Time Without Time Zone to Date in JavaScript
Best Way to Get Objects With Highest Property Value
How to Prevent Browser to Re-Set Inputs on Page Refresh
Js Li Tag Onclick Not Working on Ie8
Regexp to Match Every Occurence After N Occurences
Warning: Failed Proptype: Invalid Prop 'Component' Supplied to 'Route'
Hosting Your Own JavaScript Scripts Files (Other Than Jquery) on Fast Free Cdns Like Google
How to Pass Arguments to Addeventlistener Listener Function
How to Check Email Already Exists After Form Submission