0

我编写了一个 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;
  }

}

4

0 回答 0