有没有办法可以从包装组件中更改父状态

问题描述 投票:0回答:2

我正在尝试实现一个下拉包装器。 DropDownWrapper包装的元素有望通过onClick切换下拉列表的显示。

class DropdownMenuWrapper extends React.Component {
constructor(props) {
    super(props);
    this.state = {
      active: true,
    };

    this.handleDropDownDisplay = this.handleDropDownDisplay.bind(this);
    this.displayDropDownItems = this.displayDropDownItems.bind(this);
  }

  displayDropDownItems(menuItems, onSelectMenuItem, children) {
    return (
      menuItems.map(item => (
        <a
          className={cx('navItem')}
          key={item.value}
          onClick={() => onSelectMenuItem(children)}
        >
         {item.logo}
         {item.display}
       </a>
     ))
   );
 }

  handleDropDownDisplay() {
    this.setState({
      active: !this.state.active,
    });
  }

  render() {
    const {
      className, menuItems, onSelectMenuItem, children, label,
    } = this.props;
    return (
      <div>
        {children}
        <nav className={className} aria-label={label}>
          {this.state.active && this.displayDropDownItems(menuItems, onSelectMenuItem, children)}
        </nav>
      </div>
    );
  }
}

export default DropdownMenuWrapper;

在这里,我想在下面的包装按钮上实现下拉切换

<DropdownMenuWrapper
  menuItems={[
    { value: 'dashboard', display: 'Dashboard' },
    { value: 'myProfile', display: 'My Profile' },
  ]}
>
  <Button />
</DropdownMenuWrapper>

在这种情况下,有没有办法可以使用{children} onClick来更改父组件(DropdownMenuWrapper)的状态?

reactjs
2个回答
0
投票

值得庆幸的是,这个问题已在各种平台上得到解决,包括这个问题。我想让你开始:

您可以通过其props从父组件向下传递一个函数到子组件,并从那里使用它来改变父组件的状态。

在父组件中定义的函数负责更新父组件的状态。然后,子组件必须将该函数绑定到发生在子组件中的事件,并且一旦触发事件,该函数就会在父组件中发生,并执行其实现的更改。

您可以在现有的答案中看到详细的代码实现:How to update parent's state in React?。请原谅我,如果这不是你想要的,那么你应该让你的问题更清楚。

在将来,您应该尝试搜索现有答案,因为问题很可能已经解决。一个简单的搜索引擎搜索为我完成了这项工作,我喜欢将Stack overflow标记为搜索查询的一部分,以获得更好的答案。


0
投票

这有助于我参考:https://reactjs.org/docs/react-api.html#reactchildren

class DropdownMenuWrapper extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      active: false,
    };
  }

  displayDropDownItems = (menuItems, onSelectMenuItem) => (
    menuItems.map(item => (
      <a
        className={cx('navItem')}
        key={item.value}
        onClick={() => onSelectMenuItem(item.value)}
      >
        { item.icon && <span className={cx('icon')}>{item.icon}</span>} {item.display}
      </a>
    ))
  );

  toggleDropDown = () => {
    this.setState({
      active: !this.state.active,
    });
  };

  render() {
    const {
      className, menuItems, onSelectMenuItem, children, label,
    } = this.props;

    const childrenWithProps = React.Children.map(children, child =>
      React.cloneElement(child, { toggleDropDown: this.toggleDropDown }));

    return (
      <div>
        {childrenWithProps}
        <nav className={className} aria-label={label}>
          {this.state.active && this.displayDropDownItems(menuItems, onSelectMenuItem, children)}
        </nav>
      </div>);
  }
}

export default DropdownMenuWrapper;
© www.soinside.com 2019 - 2024. All rights reserved.