简体   繁体   English

在promise中使用setState之后,React不重新渲染

[英]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. 每次更改道具时,组件都会调用onTermChange并以承诺返回对象数组的方式获取该组件的详细信息。

The problem is that when setState is called, nothing happens and the component is not re-rendered with fresh details. 问题在于,当调用setState时,什么也不会发生,并且该组件不会使用新的细节重新呈现。

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>
    );
}
});

When you call this.setState({children: term.children}); 当您调用this.setState({children: term.children}); this equals the function it was defined in, not the react component. this等于它在其中定义的功能,而不是react组件。

Probably an exception occurs, but your promise does not call .error to trap and log it. 可能发生异常,但是您的承诺不会调用.error来捕获和记录它。

You shouldn't need to call this.forceUpdate() if you are calling this.setState . 如果正在调用this.setState则无需调用this.forceUpdate() Also, you should never call a component's render method. 另外,您永远不要调用组件的render方法。

It's hard to tell why it's not rerendering but I would a few debugger statements to see whether render is getting called. 很难说为什么不重新渲染,但是我会用一些debugger语句来查看是否调用了render I'd guess that always calling this.onTermChange in componentWillReceiveProps may be a potential issue. 我猜想总是在componentWillReceiveProps调用this.onTermChange可能是一个潜在的问题。

I came across the same problem, inspired by @z5h, I use a local viraible to refer to this outside of Promise , and it works! 在@ z5h的启发下,我遇到了同样的问题,我在Promise之外使用了一个本地viraible来指代this ,并且它起作用了!

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? 更多关于thisjs如何进行“this”关键字的工作?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM