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

时间:2018-09-05 20:43:07

标签: reactjs

我正在尝试实现下拉包装。 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)的状态?

2 个答案:

答案 0 :(得分:0)

非常感谢,此问题已在各种平台(包括该平台)上得到解决。我想让您入门:

您可以通过其道具将功能从父组件传递到子组件,然后从那里使用它来更改父组件的状态。

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

您可以在How to update parent's state in React?的现有答案中看到详细的代码实现。如果这不是您要的内容,请原谅我,在这种情况下,您应该使问题更清楚。

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

答案 1 :(得分: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;