I'm currently building a SIP phone, where the current calls are handled by a SipPhone class, and displayed on the frontend using React. SipPhone has a list of calls which trigger callbacks that a React component is listening to.
The main phone component has an initial state containing an empty Immutable List:
constructor(props) {
super(props);
...
this.state = {
calls: List(),
};
}
This calls
list is updated via an event triggered by callbacks whenever the SipPhone updates.
handleUpdate = ({ calls }) => {
const nextCalls = List(calls.map(call => {
return new Call({ ... }) // Call is an Immutable Record
});
console.log(nextCalls.toJS()); // This prints the new list I want to save
this.setState({ calls: nextCalls }, () => {
console.log(this.state.calls.toJS()); // The list is empty here
});
}
Sometimes it successfully updates the calls
list, while at other times calls
doesn't change. When I log the list before setting state, it is as it should be, however when logging in the setState callback it remains unchanged from it's previous state. Sometimes it works, sometimes it doesn't.
To further test this, I added a state variable tick
which is incremented each time I set the state here. This change is accurately reflected in the callback, while the calls list remains unchanged.
I can't seem to figure out any reason why it would be doing this. I actually began this project using a normal array rather than an immutable list, and encountered the same issue. I've been using React for quite some time now and have never run into this problem...any thoughts?
State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.
The reason why the state doesn't update immediately is because for each render, the state is immutable. …are both constants values ! So they're immutable. The state remains constant inside the render but can be changed between two renders.
The setState function takes an optional callback parameter that can be used to make updates after the state is changed. This function will get called once the state has been updated, and the callback will receive the updated value of the state.
It is the failure of the re-render to reflect the updated value of the state. The “useState” set method is asynchronous; hence, the updates are not reflected immediately.
It turns out another function in my code was setting the state in certain cases right before componentWillUpdate is called, causing it to disregard the initial call to setState. This was the source of error.
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