ReactJs:响应状态更改而更改状态

ReactJs: change state in response to state change

本文关键字:状态 响应 ReactJs      更新时间:2023-09-26

我有一个React组件,它有一个输入和一个可选的"高级输入":

[ basic ]
Hide Advanced...
[ advanced ]

如果您单击"隐藏高级",底部的高级将消失,该选项将更改为"显示高级"。这很简单,工作也很好,状态中有一个showAdvanced键,用于控制文本以及是否呈现高级输入。

然而,外部JS代码可能会更改advanced的值,在这种情况下,如果[advanced]输入当前是隐藏的,并且值与默认值不同,我想显示它。但是,用户应该可以单击"隐藏高级"再次关闭它。

所以,有人外部调用cmp.setState({advanced: "20"}),然后我想显示高级;最简单的方法就是在我的状态下更新showAdvanced。然而,似乎没有办法更新某些状态以响应React中的其他状态更改。我可以想出许多行为略有不同的解决方案,但我真的希望有这种特定的行为。

我应该把showAdvanced移到道具上吗?你能根据状态的变化改变道具吗?谢谢

好的,首先,您提到组件之外的第三方可能会调用cmp.setState()?这是一个巨大的反对反应。一个组件应该只调用它自己的setState函数——外部任何东西都不应该访问它

另一件需要记住的事情是,如果你试图再次改变状态以应对状态的改变,那就意味着你做错了什么。

当你以这种方式构建东西时,你的问题会比需要的困难得多。原因是,如果你接受任何外部事物都不能设置组件的状态,那么基本上你唯一的选择就是允许外部事物更新组件的道具,然后在组件内对它们做出反应。这简化了问题。

因此,例如,您应该考虑让过去调用cmp.setState()的任何外部事物再次调用组件上的React.renderComponent,并给出一个新的prop或prop值,例如将showAdvanced设置为true。然后,您的组件可以在componentWillReceiveProps中对此作出反应,并相应地设置其状态。下面是一个代码示例:

var MyComponent = React.createClass({
    getInitialState: function() {
        return {
            showAdvanced: this.props.showAdvanced || false
        }
    },
    componentWillReceiveProps: function(nextProps) {
        if (typeof nextProps.showAdvanced === 'boolean') {
            this.setState({
                showAdvanced: nextProps.showAdvanced
            })
        }
    },
    toggleAdvancedClickHandler: function(e) {
        this.setState({
            showAdvanced: !this.state.showAdvanced
        })
    },
    render: function() {
        return (
            <div>
                <div>Basic stuff</div>
                <div>
                    <button onClick={this.toggleAdvancedClickHandler}>
                        {(this.state.showAdvanced ? 'Hide' : 'Show') + ' Advanced'}
                    </button>
                </div>
                <div style={{display: this.state.showAdvanced ? 'block' : 'none'}}>
                    Advanced Stuff
                </div>
            </div>
        );
    }
});

因此,第一次调用React.renderComponent(MyComponent({}), elem)时,组件将被挂载,高级div将被隐藏。如果单击组件内部的按钮,它将切换并显示。如果您需要强制组件从组件外部显示高级div,只需再次调用render,如下所示:React.renderComponent(MyComponent({showAdvanced: true}), elem),它就会显示它,而不管内部状态如何。同样,如果你想对外界隐藏它,只需用showAdvanced: false调用它。

以上代码示例的额外好处是,在componentWillReceiveProps内部调用setState不会导致另一个渲染循环,因为它会在调用render之前捕获并更改状态。查看此处的文档以了解更多信息:http://facebook.github.io/react/docs/component-specs.html#updating-组件将接收道具

不要忘记,在已经安装的组件上再次调用renderComponent并不会再次安装它,它只是告诉react更新组件的props,然后react将进行更改,运行组件的生命周期和渲染功能,并实现它的dom困难魔术。

在下面的评论中修改了答案。


我最初的错误答案:

当接收到新的状态或道具时,将运行生命周期函数componentWillUpdate。您可以在此处找到相关文档:http://facebook.github.io/react/docs/component-specs.html#updating-组件将更新

如果在调用外部setState时,在componentWillUpdate中将showAdvanced设置为true,则应该会得到所需的结果。

EDIT:另一个选项是让对setState的外部调用将showAdvanced: true包含在其新状态中。