【问题标题】:ReactJS: Control a child state from the child and the parentReactJS:从孩子和父母控制一个孩子的状态
【发布时间】:2015-06-14 05:15:11
【问题描述】:

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

假设您在父级中有一个显示模式的链接

在模式中,您有一个“X”来关闭它。

我知道我可以通过 props 从父级更改模态框的状态

// 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 的方式是将打开/关闭逻辑存储在 modal 变量中。

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?

【问题讨论】:

    标签: reactjs react-jsx


    【解决方案1】:

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

    1. 让孩子“受控”,就像具有valueonChange 属性的表单输入一样,其中输入的所有者控制输入。
    2. 让孩子“不受控制”,就像没有value 的表单输入一样。

    第二种选择在前面似乎更快,但就像在 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。)

    因此,现在您可以使用完全由父控制的 Modal,但您已经删除了一部分样板文件,围绕创建一个将值设置为 false 并将其传递给 modal 的函数。

    【讨论】:

    • 这个答案很糟糕。
    【解决方案2】:

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

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

    那么当你点击child上的关闭按钮时,它会调用parent的函数

    【讨论】:

    • 嗯,我不知道你能做到。这可能会奏效,但仍然让我感到困扰的是,打开和关闭模态的逻辑不是 in 模态 jsx 变量。似乎我应该能够随身携带这种逻辑,无论我把模态放在哪里。
    • 如果你在父节点上为{ modal: { display: false }} 设置状态并将其作为道具传递并在模态中使用 componentWillReceiveProps(props) 方法会怎样?这将允许您保持模式显示的状态,而无需从父组件传递 close 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 2014-05-14
    相关资源
    最近更新 更多