javascript 如果我不应该在 componentWillUpdate 中调用 setState,我该如何更新状态(使用 ReactJS)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28945089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:48:35  来源:igfitidea点击:

How do I update the state (using ReactJS) if I should not call setState in componentWillUpdate?

javascriptreactjs

提问by hdavidzhu

When I setStatein componentWillUpdate, componentWillUpdateruns in an infinite loop that doesn't stop getting triggered.

当 I setStatein 时componentWillUpdate,会componentWillUpdate在无限循环中运行,并且不会停止触发。

This never gives my rendera chance to reflect my changes. How can I change the state if I shouldn't use componentWillUpdate?

这从来没有给我render机会反映我的变化。如果我不应该使用,我该如何更改状态componentWillUpdate

Edit: I already have some understanding that setStateshould not be called in componentWillUpdate. I'm just confused what I should do as an alternative.

编辑:我已经有了一些setState不应在 componentWillUpdate 中调用的理解。我只是很困惑我应该做什么作为替代方案。

Edit #2: I started with componentWillReceivePropsbut I can't seem to trigger this function when my Parent component changes state. I provide that state from the parent as a props to my child.

编辑 #2:我开始componentWillReceiveProps时,但当我的父组件更改状态时,我似乎无法触发此功能。我将父母的状态作为道具提供给我的孩子。

回答by zaynetro

First thing to do is to check official documentation for this method (link). Where you can read when the function is actually called.

首先要做的是查看此方法的官方文档(链接)。您可以在实际调用函数时读取的位置。

Then read common mistake(note):

然后阅读常见错误(注):

You cannot use this.setState() in this method. If you need to update state in response to a prop change, use componentWillReceiveProps instead.

您不能在此方法中使用 this.setState()。如果您需要更新状态以响应 prop 更改,请改用 componentWillReceiveProps。

You change the state and React automatically calls componentWillUpdate.

你改变状态,React 会自动调用componentWillUpdate.

回答by Marcus Junius Brutus

I understand this is cautioned against in the guidebut I am not sure I can see the problem with calling setStatefrom within componentWillUpdate. True, it may result in infinite recursion unlessof course you provide a bottom to that recursion (a way to break out of it). E.g. a way could be to check the second (nextState) parameter in componentWillUpdateand not invoke setStateagain if some condition is met (which is when the recursion ends).

我知道指南中警告不要这样做,但我不确定我是否可以看到setState从内部调用的问题componentWillUpdate。确实,它可能会导致无限递归,除非您当然为该递归提供一个底部(一种打破它的方法)。例如,一种方法可能是检查第二个 ( nextState) 参数,如果满足某些条件(即递归结束时),则componentWillUpdate不再调用setState

As a minimal example, imagine a component that has no properties at all, only two pieces of state. Further imagine that the second piece of state is asynchronously obtained from the first. E.g. the first piece of state could be some parameter to provide to an Ajax call, and the second piece of state is the result of that call. So basically you call this.setStateto configure the parameters and then inside componentWillUpdateyou can do something like the following (to keep things simple I use a window.setTimeoutas a placeholder for an Ajax call):

作为一个最小的例子,想象一个完全没有属性的组件,只有两个状态。进一步想象第二个状态是从第一个状态异步获取的。例如,第一部分状态可以是提供给 Ajax 调用的某个参数,而第二部分状态是该调用的结果。所以基本上你调用this.setState来配置参数,然后在里面componentWillUpdate你可以做如下的事情(为了简单起见,我使用 awindow.setTimeout作为 Ajax 调用的占位符):

const ComponentWithAsyncState = React.createClass({
    getInitialState: function() {
        return {
            ajaxParams: '',
            ajaxResult: ''
        };
    },
    setAjaxParams: function(params) {
        this.setState({ajaxParams: params});
    },
    componentWillUpdate: function(_, nextState) {
        if (nextState.ajaxParams!=this.state.ajaxParams)
            window.setTimeout(function imagineThisIsAjax() {
                this.setState({ajaxResult: `result from ${nextState.ajaxParams}`});
            }.bind(this), 2000);
    },

When, (e.g. through some controls managed by this component) the ajaxParamschange, the sequence of actions will be something like (where ~~>denotes asynchronicity):

当(例如通过此组件管理的某些控件)发生ajaxParams更改时,操作序列将类似于(其中~~>表示异步性):

setAjaxParams --> this.setState --> componentWillUpdate ~~> imagineThisIsAjax --> this.setState --> componentWillUpdate

I.e. the second call to componentWillUpdatewill not result in a further this.setStateand thus the recursion will end there.

即第二次调用componentWillUpdate不会导致进一步this.setState,因此递归将在那里结束。