ReactJS:从子级和父级控制子级状态

时间:2015-04-09 01:43:04

标签: reactjs react-jsx

我有一个相当简单的问题,而且我不确定如何使用React的单向数据流来解决它。

假设您在父级中有一个显示模态

的链接

在模态中,你有一个" X"关闭它。

我知道我可以通过道具

从父母改变模态的状态
// In the parent
<Modal display={this.state.showModal} />

// In the modal
<div className={this.props.display ? "show" : "hide"}>
  <a className="close">&times;</a>
  ...
</div>

我知道如何关闭模态,但不是两者兼而有之。不确定如何保持父模式和子模式共享和控制的状态。

更新

在尝试尽可能保持模块化时,我认为React的方法是将开/关逻辑存储在模态变量中。

var ParentThing = React.createClass({
  ...
  render (
    <Modal /> // How can I call this.open in the modal from here?
  )
});

var Modal = React.createClass({
  setInitialState: function() {
    return {
      display: false
    }
  },
  close: function() {
    this.setState({ display: false });
  },
  open: function() {
    this.setState({ display: true });
  },
  render: function() {
    return (
      <div className={this.state.display ? "show" : "hide"}>
        <a className="close" onClick={this.close}>&times;</a>
      </div>
    )
  }
});

我看到了这种方法,但它似乎比我需要做的更多。 Reactjs: how to modify child state or props from parent?

2 个答案:

答案 0 :(得分:16)

在React中有两种方法可以处理这种事情:

  1. 让孩子“受控制”,就像具有valueonChange属性的表单输入一样,输入的所有者控制输入。
  2. 让孩子“不受控制”,就像没有value的表单输入一样。
  3. 第二种选择似乎预先更快,但就像在React中管理表单输入的集合一样,使用完全控制的组件的优势随着复杂性的构建和在任何完全描述UI的需要而变得明显em>点和时间增加。 (如果你很好奇为什么受控组件在大多数情况下比不受控制的更好,请参见FakeRainBrigand中的this excellent answer。)

    但是,就像表单输入一样,您的组件无法控制不受控制。如果用户传递了displayonClose属性,例如Austin Greco's answer,则您拥有受控模式,并且父级完全决定何时显示或隐藏模态。

    如果用户,您可以跳过使用属性,而是委托由模态组件上的公共方法管理的内部状态:

    var ParentThing = React.createClass({
      ...
      render: function() {
        return <Modal ref="modal" />;
      },
    
      handleSomeClick: function() {
        this.refs.modal.open();
      }
    });
    
    var Modal = React.createClass({
      setInitialState: function() {
        return {
          display: false
        }
      },
      close: function() {
        this.setState({ display: false });
      },
      open: function() {
        this.setState({ display: true });
      },
      render: function() {
        return (
          <div className={this.state.display ? "show" : "hide"}>
            <a className="close" onClick={this.close}>&times;</a>
          </div>
        )
      }
    });
    

    如果您喜欢受控Modal组件的想法,但又不想进行所有样板输入,那么您甚至可以为Modal实现类似valueLink属性的内容来简化此操作图案。

    var ParentThing = React.createClass({
      ...
      mixins: [React.addons.LinkedStateMixin],
    
      getInitialState: function() {
        return { showModal: false };
      },
    
      render: function() {
        return <Modal displayLink={this.linkState("showModal")} />;
      },
    
      handleSomeClick: function() {
        this.setState({showModal: true});
      }
    });
    
    var Modal = React.createClass({
      close: function() {
        this.props.displayLink.requestChange(false);
      },
    
      render: function() {
        return (
          <div className={this.props.displayLink.value? "show" : "hide"}>
            <a className="close" onClick={this.close}>&times;</a>
          </div>
        )
      }
    });
    

    (见my blog post on creating custom components that work with linkState/valueLink for more info。)

    所以现在你可以获得使用完全父控制模态的好处,但是你已经删除了一部分模板,创建了一个函数,将值设置为false并将其传递给模态。 / p>

答案 1 :(得分:6)

您可以将回调作为道具传递给子组件:

// In the parent
<Modal display={this.state.showModal} onClose={this.closeModal} />

// In the modal
<div className={this.props.display ? "show" : "hide"}>
  <a className="close" onClick={this.props.onClose}>&times;</a>
  ...
</div>

然后当您单击子项上的关闭按钮时,它将调用父项的功能