9

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>
    );
}
});
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Tom
  • 1,546
  • 2
  • 20
  • 42

3 Answers3

2

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.

Mark Bolusmjak
  • 23,606
  • 10
  • 74
  • 129
1

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.

paulshen
  • 374
  • 1
  • 2
  • 7
0

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?

Community
  • 1
  • 1
Jonas Hao
  • 191
  • 1
  • 4
  • 11