I have a React class, and it wants to render an object shown below:
data: {
title: "haha",
description: {
country: "US",
year: "1996"
}
}
But, when React wants to render it, it gives an error.
Uncaught Error: Invariant Violation: receiveComponent(...): Can only update a mounted component
I think the problem is in the getInititalState, I declare my data as an empty object, so when I get my full data object after the timeout, React will try to map my data object to the component, but it gives error.
But one interesting thing is, I have no problem accesing this.props.title.title, but not this.props.title.description.country, it will give undefined
But, when I console.log it, I could see my object. But React cant access it!
My guessing is when React initializing from the empty object, it will only init the virtual DOM with the 1st and 2nd level of the data object.
That the reason, when I try to access this.props.data.data.title is OK but not this.props.data.data.description.country
Below is my code
var BookBox = React.createClass({
getInitialState: function() {
return { data: {} };
},
componentWillMount: function() {
var that = this;
setTimeout(function() {
console.log('timeout');
that.setState({
data: {
title: "haha",
description: {
country: "US",
year: "1996"
}
}
});
}, 2000);
},
render: function() {
return (
<div>
<h1>{this.state.data.title}</h1>
<TestBox title={this.state.data} />
</div>
);
}
});
var TestBox = React.createClass({
render: function() {
console.log(this.props.title);
return (
<div>
<p>{ this.props.title.description.country }</p>
<p>{ this.props.title.title }</p>
</div>
);
}
})
May I know what is the best way to handle this problem? should i init my data object structure in the getInitialState or there is a better way?
I think you are getting Can only update a mounted component
error because you are using componentWillMount
and settimeout
together, but you dont know if the component has been mounted by the time settimeout
function fires.
Since you know what your state is beforehand, I think it is best to return your data from getInitialState
function.
You can also use componentDidMount
instead of componentWillMount
function. That way you can be sure the component is mounted when componentDidMount
is called.
Any time time you are using asycn functions like settimeout
or a xhr call, you should use this.isMounted()
in the callback function, to check that the component is still mounted by the time the callback fires.
For example, if you didnt know the state beforehand, you could fire an xhr call in the componentDidMount
function, check this.isMounted()
in the success callback and setState
.
As for the error on <p>{ this.props.title.description.country }</p>
line: At initial render this.state.data
(BookBox) is an empty object so is this.props.title
(TestBox). Accessing empty object's ({ }
) title
property is undefined
. No problem there. Accessing description
is also undefined
. But accessing undefined
's country
is error. To avoid this error you can create a description
variable: description = this.props.title.description || {}
and use <p>{description.country}</p>
to make sure your code doesnt break if this.props.title
is empty.
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