setState function or the updater function returned by the React. useState() Hook in class and function components, respectively. State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately.
setState or useState do not immediately mutate the state but create a pending state transition. Accessing state immediately after calling the updater method can potentially return the old value.
React do not update immediately, although it seems immediate at first glance.
Use the useEffect hook to wait for state to update in React. You can add the state variables you want to track to the hook's dependencies array and the function you pass to useEffect will run every time the state variables change.
Your state needs some time to mutate, and since console.log(this.state.boardAddModalShow)
executes before the state mutates, you get the previous value as output. So you need to write the console in the callback to the setState
function
openAddBoardModal() {
this.setState({ boardAddModalShow: true }, function () {
console.log(this.state.boardAddModalShow);
});
}
setState
is asynchronous. It means you can’t call it on one line and assume the state has changed on the next.
According to React docs
setState()
does not immediately mutatethis.state
but creates a pending state transition. Accessingthis.state
after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
setState
asyncThis is because
setState
alters the state and causes rerendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive.Thus the
setState
calls are asynchronous as well as batched for better UI experience and performance.
Fortunately setState()
takes a callback. And this is where we get updated state.
Consider this example.
this.setState({ name: "myname" }, () => {
//callback
console.log(this.state.name) // myname
});
So When callback fires, this.state is the updated state.
You can get mutated/updated
data in callback.
Since setSatate is a asynchronous function so you need to console the state as a callback like this.
openAddBoardModal(){
this.setState({ boardAddModalShow: true }, () => {
console.log(this.state.boardAddModalShow)
});
}
For anyone trying to do this with hooks, you need useEffect
.
function App() {
const [x, setX] = useState(5)
const [y, setY] = useState(15)
console.log("Element is rendered:", x, y)
// setting y does not trigger the effect
// the second argument is an array of dependencies
useEffect(() => console.log("re-render because x changed:", x), [x])
function handleXClick() {
console.log("x before setting:", x)
setX(10)
console.log("x in *line* after setting:", x)
}
return <>
<div> x is {x}. </div>
<button onClick={handleXClick}> set x to 10</button>
<div> y is {y}. </div>
<button onClick={() => setY(20)}> set y to 20</button>
</>
}
Output:
Element is rendered: 5 15
re-render because x changed: 5
(press x button)
x before setting: 5
x in *line* after setting: 5
Element is rendered: 10 15
re-render because x changed: 10
(press y button)
Element is rendered: 10 20
setState()
does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState()
a potential pitfall. Instead, use componentDidUpdate
or a setState
callback (setState(updater, callback)
), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the updater argument below.
setState()
will always lead to a re-render unless shouldComponentUpdate()
returns false. If mutable objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate()
, calling setState()
only when the new state differs from the previous state will avoid unnecessary re-renders.
The first argument is an updater function with the signature:
(state, props) => stateChange
state
is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props. For instance, suppose we wanted to increment a value in state by props.step:
this.setState((state, props) => {
return {counter: state.counter + props.step};
});
This callback is really messy. Just use async await instead:
async openAddBoardModal(){
await this.setState({ boardAddModalShow: true });
console.log(this.state.boardAddModalShow);
}
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