【问题标题】:How to make a React component ‘communicate’ with another React component?如何让一个 React 组件与另一个 React 组件“通信”?
【发布时间】:2018-03-14 10:58:57
【问题描述】:

我有一个父 jsx 组件,其中包含 2 个不同的 jsx 组件。 一个组件是一个按钮,另一个是一个 div,当您单击它时会自行打开和关闭(它有一个单击处理程序和打开或关闭状态)。 我现在想为按钮添加打开和关闭 div 的功能。 实现这一点的唯一方法是从父组件向下传递一个处理函数到按钮,将 div 的打开和关闭状态移动到父组件,然后将状态作为 props 向下传递给 div?我问的原因是这个特定的 div 组件用于许多不同的组件,删除打开和关闭状态会影响许多不同的父组件。

【问题讨论】:

  • 您可以向它传递一个 isOpen 道具,然后在 componentWillReceiveProps 上设置组件内部的状态。这是一种将功能留给组件但也通过它的父级影响它的方法。
  • 您的用例是提升状态的完美案例,即使它可能需要在您的应用程序中进行一些更改,您也应该继续使用它。检查这个问题何时提升状态stackoverflow.com/questions/46594900/…
  • "实现这一点的唯一方法是从父组件向下传递一个处理函数到按钮,将 div 的打开和关闭状态移动到父组件,并将状态向下传递给 div作为道具?”不,您可以按照@MatanBobi 的建议使用该策略来允许外部操作

标签: reactjs jsx


【解决方案1】:

这是一个允许外部状态操作的代码示例,您可以在其中混合使用按钮或 div 来切换状态。您可以扩展 Collapsible 组件以使用传递的道具来更新状态。

class Collapsible extends React.Component {
  constructor(props){
    super(props);
    this.state = { isOpen: this.props.isOpen !== false };
    this.toggleOpen = this.toggleOpen.bind(this);
  }
  componentWillReceiveProps({ isOpen }) {
    this.setState({ isOpen });
  }
  toggleOpen(){
   this.setState((prevState) => ({ isOpen: !prevState.isOpen }))
  }
  render() {
    let display = this.state.isOpen ? null : "none";
    return (
      <div
        className="collapsible"
        onClick={this.toggleOpen}
      >
        <header> header </header>
        <div style={{ display }}>{this.props.children}</div>
      </div>
    );
  }
}

class Parent extends React.Component {
  constructor(props){
    super(props);
    this.state = { isOpen: true };
    this.toggleOpen = this.toggleOpen.bind(this);
  }

  toggleOpen(){
   this.setState((prevState) => ({ isOpen: !prevState.isOpen }))
  }

  render() {
    return (
      <div className="parent">
        <Collapsible isOpen={this.state.isOpen}>content</Collapsible>
        <button onClick={this.toggleOpen}>
          toggle
        </button>
      </div>
    );
  }
}

【讨论】:

    【解决方案2】:

    这是另一个代码示例,希望对您有所帮助:

    我使用Container 的本地状态并将其传递给子组件。在更大的应用程序中,我建议您使用 Redux 之类的东西来管理您的状态。

    中心思想是父组件将一个可以“改变其状态”的函数传递给子按钮。它还将当前的isOpen 状态传递给面板。点击按钮会改变parent的状态,从而触发reflow,从而更新collapsable。

    供将来参考:

    import React from "react";
    import { render } from "react-dom";
    
    const Collapsable = ({ isOpen }) =>
      isOpen ? (
        <div
          style={{
            border: "1px solid orange",
            padding: "1rem",
            background: "maroon",
            color: "white"
          }}
        >
          {" "}
          Hey, I'm open{" "}
        </div>
      ) : (
        <div>Oh no...closed :(</div>
      );
    
    const Button = ({ openPanel }) => (
      <button onClick={() => openPanel()}>Open Panel</button>
    );
    
    class Container extends React.PureComponent {
      state = { open: false };
    
      openPanel = () => {
        this.setState({
          ...this.state,
          open: this.state.open ? false : true
        });
      };
    
      render() {
        return (
          <div>
            <Button openPanel={this.openPanel} />
            <Collapsable isOpen={this.state.open} />
          </div>
        );
      }
    }
    
    const App = () => (
      <div>
        <Container />
      </div>
    );
    
    render(<App />, document.getElementById("root"));
    

    【讨论】:

    • @mr-baudin 您不应该在渲染中使用箭头函数,因为它会在每个渲染上创建一个新函数。相反,在构造函数中绑定函数或使用 curry 进行绑定。此外,当您设置新状态时,无需传播最后一个状态 setState 仅更改它需要更改的属性,并且当您编辑以前的状态时,您应该使用 setState((prevState) =&gt; ({isOpen: !prevState.isOpen}))
    • @MatanBobi 感谢您的反馈,您是对的。只是为了记账:don't use arrow functions in render。你对国家的看法也是对的。我不知道谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-09
    • 2023-01-07
    • 2022-10-04
    • 1970-01-01
    • 2021-03-16
    • 2018-01-26
    • 2019-10-23
    相关资源
    最近更新 更多