首页 文章

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

提问于
浏览
12

我有一个相当简单的问题,我不知道如何使用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>

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

UPDATE

在尝试尽可能保持模块化时,我认为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 回答

  • 6

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

    // 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>
    

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

  • 16

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

    • 使子"controlled,"就像具有 valueonChange 属性的表单输入一样,输入的所有者控制输入 .

    • 让孩子"uncontrolled,"就像没有 value 的表单输入一样 .

    第二种选择似乎前期更快,但就像在React中管理表单输入的集合一样,使用完全受控组件的优势随着复杂性的构建以及在任何时间点完全描述UI的需求而变得明显 . (参见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>
        )
      }
    });
    

    (有关更多信息,请参阅我在博客文章中创建与linkState / valueLink一起使用的自定义组件 . )

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

相关问题