Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React does not rerender after setState used in promise

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>
    );
}
});
like image 979
Tom Avatar asked Nov 05 '14 15:11

Tom


2 Answers

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.

like image 65
Mark Bolusmjak Avatar answered Nov 06 '22 13:11

Mark Bolusmjak


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.

like image 28
paulshen Avatar answered Nov 06 '22 13:11

paulshen