Reputation: 1565
Every time the props are changed, the component will call onTermChange and get the details for this component with a promise that returns an array of objects.
The problem is that when setState is called, nothing happens and the component is not re-rendered with fresh details.
module.exports = React.createClass({
displayName: 'TaxonomySelect',
getInitialState: function () {
return {
children: undefined
};
},
componentDidMount: function () {
this.onTermChange(this.props.term);
},
componentWillReceiveProps: function (nextProps) {
this.props.term = this.props.term || null;
if (this.props.term) {
this.onTermChange(nextProps.term.id);
} else {
this.onTermChange(nextProps.term);
}
},
onTermChange: function (term) {
this.setState({children: undefined});
TaxonomyStore.getTerm(this.props.term)
.bind(this)
.then(function (term) {
TaxonomyStore.merge(9999,{
description: 'No specific topic',
id: 9999
});
if (term.path && term.path.length === 3) {
term.children.unshift(TaxonomyStore.get(9999));
}
console.log(term.id, term.children);
this.setState({children: term.children});
this.forceUpdate();
this.render();
});
},
onSelect: function (id) {
if (this.props.onChange) {
this.props.onChange(TaxonomyStore.get(id));
}
},
render: function () {
if (!Array.isArray(this.state.children) || this.state.children.length < 1) {
return null;
};
var options = this.state.children.map(function (term) {
return {
value: term.id.toString(),
label: term.description
};
});
var value = this.props.value && this.props.value.toString();
return (
<div>
<Select name={this.props.name} value={value} options={options} onChange={this.onSelect} />
</div>
);
}
});
Upvotes: 9
Views: 10209
Reputation: 301
I came across the same problem, inspired by @z5h, I use a local viraible to refer to this
outside of Promise
, and it works!
In your case:
onTermChange: function (term) {
this.setState({children: undefined});
let _this = this; // change
TaxonomyStore.getTerm(this.props.term)
.bind(this)
.then(function (term) {
TaxonomyStore.merge(9999,{
description: 'No specific topic',
id: 9999
});
if (term.path && term.path.length === 3) {
term.children.unshift(TaxonomyStore.get(9999));
}
console.log(term.id, term.children);
_this.setState({children: term.children}); //change
});
}
More about this
in js
: How does the “this” keyword work?
Upvotes: 0
Reputation: 24419
When you call this.setState({children: term.children});
this
equals the function it was defined in, not the react component.
Probably an exception occurs, but your promise does not call .error
to trap and log it.
Upvotes: 2
Reputation: 384
You shouldn't need to call this.forceUpdate()
if you are calling this.setState
. Also, you should never call a component's render
method.
It's hard to tell why it's not rerendering but I would a few debugger
statements to see whether render
is getting called. I'd guess that always calling this.onTermChange
in componentWillReceiveProps
may be a potential issue.
Upvotes: 1