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

IT技术 reactjs react-jsx
2021-05-23 04:03:53

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

我知道如何关闭模态,但不能同时关闭。不确定如何保持由父模态和子模态共享和控制的状态。

更新

为了尽可能保持module化,我认为 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:如何从父级修改子状态或props?

2个回答

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

  1. 使孩子“受控”,就像带有valueandonChange属性的表单输入一样,输入所有者控制输入​​。
  2. 让孩子“不受控制”,就像没有value.

第二种选择看起来更快,但就像在 React 中管理一组表单输入一样,使用完全受控组件的优势变得明显,因为构建的复杂性以及在任何点和时间完全描述您的 UI 的需求增加。如果您很好奇为什么在大多数情况下受控组件比不受控制的更好,请参阅FakeRainBrigand 的这个出色的回答。)

然而,就像表单输入一样,您的组件没有理由不能被控制不受控制。如果用户传递displayonClose属性,如Austin Greco 的 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 组件的想法,但不想做所有的样板输入,您甚至可以实现类似valueLinkModal 属性的东西来简化这种模式。

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>
    )
  }
});

(有关更多信息linkStatevalueLink请参阅我关于创建与/一起使用的自定义组件的博客文章。)

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

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

// 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 的函数