I'm working with a library which needs to be initialized in componentDidMount according to their documentation but I am not getting the expected results when I update the state, like so:
class ChartContents extends React.Component {
constructor() {
super();
this.state = { stxx: {} };
}
componentDidMount() {
let stxx=new STXChart(this.chartContainer);
stxx.newChart("SPY", sampleData);
this.setState({stxx});
console.log(this);
console.log(this.state);
}
render()
{
const Style = {
height:'600px',
position:'relative',
width:'800px'
}
return (
<div id="quickStart" className="chartContainer" style={Style} ref={(c)=>this.chartContainer=c}></div>
);
}
}
When I view the object in the debugger I find my state was updated on the object ChartContents with the newly created chart but when I try to access it, it returns the empty object it was initialized with. I did also see the eslint warning and I was wondering how to solve this problem. Thanks!

setState is not guaranteed to update state immediately, state updates are batched. When/where are you accessing state in both cases?
@Aweary the console.log statements are currently in the componentDidMount function, however the result is the same in the render function, I can find the state updated on this (the class object) but not this.state
the console.log statements are currently in the componentDidMount function
There's no guarantee that state updates will complete immediately, since they're batched. See the docs on setState
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.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.
Logging state immediately after calling setState will likely give you the previous state since it hasn't actually updated yet. If you want to perform a side effect or something after the state has been updated, you can provide a callback to setState
this.setState(newState, () => {
// this callback will be called once state is updated
}
however the result is the same in the render function, I can find the state updated on this (the class object) but not this.state
Are you saying that this.state does not contain the updated state when render is called after you setState in componentDidMount?
@Aweary You are correct, I did read the docs on setState and saw state is not guaranteed to be updated right away but when I saw only the state on this was updated with the new state but not this.state within the same function in the program I thought this strange behavior and I was doing something wrong. Also when I said:
however the result is the same in the render function, I can find the state updated on this (the class object) but not this.state
I should have been more specific, the first render give me the same output, which is a unexpected as it is called before componentDidMount() and I was showing the STXChart on the state of this but not this.state but after the second render both this and this.state contain the new chart object and not the empty object it was initialized with. I expected them both to be updated at the same time, the inconsistency is what made me question it.
Here is a more verbose output:
class ChartContents extends React.Component {
constructor() {
super();
this.state = { stxx: {} };
}
componentDidMount() {
let stxx=new STXChart(this.chartContainer);
stxx.newChart("SPY", sampleData);
this.setState({stxx});
console.log('DID MOUNT');
console.log(this);
console.log(this.state);
}
render()
{
const Style = {
height:'600px',
position:'relative',
width:'800px'
}
console.log('RENDER');
console.log(this);
console.log(this.state);
return (
<div id="quickStart" className="chartContainer" style={Style} ref={(c)=>this.chartContainer=c}></div>
);
}
}

The red arrows show where it's inconsistent and the green arrow shows where both the state on this and this.state match. Again, the inconsistency is what concerned me, I'm just trying to understand if this is because of something I am doing wrong or if this is expected behavior.
@AvaKathrynShaw When you log in Chrome, it's not creating a copy of the object. It actually reads the data from the object when you expand it in the console. Hence, when you expand the object in the console in this case, you're seeing the value it has now, not the value it had when you logged it.
@syranide Thank you! I should have thought to look into how the browser worked as well, I'm new to React and assumed I did something wrong. Will close issue.
Most helpful comment
There's no guarantee that state updates will complete immediately, since they're batched. See the docs on
setStateLogging state immediately after calling
setStatewill likely give you the previous state since it hasn't actually updated yet. If you want to perform a side effect or something after the state has been updated, you can provide a callback tosetStateAre you saying that
this.statedoes not contain the updated state whenrenderis called after yousetStateincomponentDidMount?