【问题标题】:How do I manage state on a React component that can have state changed from the parent or from events upon it?如何管理可以从父级或事件上更改状态的 React 组件上的状态?
【发布时间】:2015-12-18 18:10:51
【问题描述】:

我正在尝试制作一个自定义复选框组件(实际上是三态,但这无关紧要,只是说我不只是使用 INPUT),我不确定如何使它能够从点击本身和从父级下来的值集更改“检查性”。

目前,我将它作为一个自给自足的组件工作,该组件采用 onChange 道具和处理程序回调,它调用该回调以在单击后将值发送给父组件。它使用状态来存储已选中状态,由显示引用。

如果它只是一个显示的检查,价值是从外部管理的,我自然会使用道具。如果它只是一个自给自足的复选框组件,它采用初始值然后只响应点击,我会使用状态,就像我一样,但我的问题是我希望它可以点击来打开和关闭,并且允许父母也可以打开和关闭它。

我是 React 和“React 思维方式”的初学者,所以我怀疑我只是在处理这个错误。我的印象是,这样做的正确方法是让它成为一个仅显示组件,将点击传递给父级处理,然后接收来自父级的值更改的道具更新,但是在我看来,这将使组件的可重用性大大降低。

那么我将如何从内部和父源中更改复选框?

也欢迎提供相关链接。

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    你可以把checkbox当成一个哑组件,也就是说它不保存任何内部状态,只是通过props从外部接收数据然后渲染他们。可以看哑组件的详细定义here

    同时,当复选框被点击时,此类事件将由组件的父级或事件祖先处理,这称为反向数据流,在 Facebook 的 Thinking in React 中有描述 博文。

    此外,为了决定哪个组件应该保持某些状态,我发现以下准则非常有用:

    记住:React 是关于单向数据沿着组件层次结构向下流动的。可能无法立即清楚哪个组件应该拥有什么状态。 这通常是新手最难理解的部分,所以请按照以下步骤来弄清楚:

    对于应用程序中的每个状态:

    • 识别基于该状态呈现某些内容的每个组件。
    • 找到一个共同的所有者组件(在层次结构中需要状态的所有组件之上的单个组件)。
    • 公共所有者或层次结构中更高级别的其他组件应拥有该状态。
    • 如果您找不到拥有状态有意义的组件,请创建一个仅用于保存状态的新组件,并将其添加到公共所有者组件上方的层次结构中的某个位置。

    伪代码sn-p:

    const Checkbox = React.createClass({
      // Propagate the event to parents
      onClick(evt) {
        if (this.props.handleClick) {
          this.props.handleClick({checked: evt.target.value});
        }
      },
    
      render() {
        return (
          this.props.checked ? 
            <Input onClick={this.onClick} type="checkbox" label="Checkbox" checked></Input> : 
            <Input onClick={this.onClick} type="checkbox" label="Checkbox"></Input>
        );
      }
    });
    
    const Container = React.createClass({
      handleClick(evt) {
        // Change the container's state, which eventually changes the checkbox's view via props.
        this.setState({checked: evt.checked});
      },
    
      render() {
        return (
          <div><Checkbox checked={this.state.checked} handleClick={this.handleClick}></Checkbox></div>
        );
      }
    });
    

    【讨论】:

    • 是的,这听起来像是我需要做的。我开始将我的想法从我旧的“桶旅”想法(其中数据由单个组件根据需要处理)转移到 React 使用的更多“中心控制点”的想法。我只是没有意识到哲学是如此包罗万象,这是我的问题。也感谢文章链接。
    【解决方案2】:

    您仅从父级更改它。

    class ParentComponent extends React.Component{
      handleChildCheck(){
        this.setState({
         childChecked: !this.state.childChecked
        })
      }
      render(){
        return(
          <ChildComponent checked={this.state.childChecked} handleCheck={this.handleChildCheck.bind(this)} />
        )
     }
    }
    

    现在,如果您想从&lt;ChildComponent/&gt; 控制选中状态,只需从&lt;ChildComponent/&gt; 调用this.props.handleCheck()

    这样,控件将始终在&lt;ChildComponent/&gt; 中通过this.props.handleCheck()&lt;ParentComponent/&gt; 中通过this.handleChildCheck() 可用。

    【讨论】:

    • 好吧,在看了这个之后,我自己又胡思乱想了一点,我想我明白了。基本上, Checkbox 组件(子组件)应该只处理检查属性,正确显示自身,并将任何交互(点击)事件传递给父处理程序(handleChildCheck,在您的示例中)。其他所有内容,包括单击复选框实际设置检查属性的逻辑,都应该在父级中处理并通过道具下降到子级。听起来对吗?
    • 是的,正确的。这符合 React 的思维方式!
    猜你喜欢
    • 2017-09-05
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2016-12-21
    相关资源
    最近更新 更多