反应道具

时间:2018-05-03 21:27:42

标签: reactjs typescript react-bootstrap high-order-component

我编写了一个React / Typescript高阶组件,以便根据用户的权限显示/隐藏组件。

在我使用ReactBootstrap NavDropdown尝试之前,它工作得很好。单击包装的MenuItems不会关闭菜单。

我意识到“onSelected”道具(由NavDropdown组件应用)没有传播到MenuItem。为了解决这个问题,我添加了代码来手动传播道具,但点击仍然没有关闭菜单。

谁能告诉我哪里出错?

更新:进一步测试后,即使包装在React.Fragment中也会导致此问题。

导航:

export class SettingsButton extends React.Component<any, any> {
  public render() {
    return <NavDropdown title="My Dropdown" key='settingsButton' id='settingsButton' noCaret >
      <LinkContainer to="/LogIn" onClick={() => { AuthStore.LogOut(); }}>
        <MenuItem>Log Out</MenuItem>
      </LinkContainer>
      <PermissionDependent isAdmin {...this.props} >
        <LinkContainer to="/OperationsEditor">
          <MenuItem>Operation</MenuItem>
        </LinkContainer>
      </PermissionDependent>
    </NavDropdown >;
  }
}

打包机:

import * as React from 'react';
import { ReactElement } from 'react';

interface AdminItemProps {
  isAdmin?: boolean;
  isReadOnly?: boolean;
  canViewInventories?: boolean;
  canViewFinancial?: boolean;
}

export class PermissionDependent extends React.Component<AdminItemProps & any, any> {
  public render() {
    let canView = false;
    if (this.props.isAdmin && this.props.isAdmin === true){ // AuthStore.currentUser.isAdmin) {
      canView = true;
    }
    const { children } = this.props;
    return <React.Fragment>{canView && this.ProcessChildren(children, { ...this.props })}</React.Fragment>;
  }

  ProcessChildren(children: any, props: any) {
    if (children instanceof Array) {
      const result = (children as Array<React.ReactNode>).map(child => {
        if (React.isValidElement(child)) {
          return this.ApplyChildProps(child, { ...this.props });
        }
      });
      return result;
    }
    else {
      const child: React.ReactNode = children;
      var mapped = this.ApplyChildProps(child, { ...this.props });
      return mapped;
    }
  }

  ApplyChildProps(child: React.ReactNode, props: any) {
    if (React.isValidElement(child)) {
      const childProps = child.props as any;
      const newProps: any = {};
      
      const reflectedTypes: any = (child.type as any).propTypes;
      if (reflectedTypes) {
        Object.keys(reflectedTypes).map(key => {
          if (key != "children" && !childProps[key]) {
            const value = props[key];
            if (value) {
              newProps[key] = value;
            }
          }
        });
      }
      const childChildren: any = childProps["children"];
      const clonedChildren: any = this.ProcessChildren(childChildren, props);
      const finalProps: any = { key: Math.random(), children: clonedChildren, ...newProps, ...childProps };
      return React.cloneElement(child, finalProps);
    }
    return child;
  }

}

0 个答案:

没有答案