Реагировать на компоненты высокого порядка, блокирующие распространение реквизита - PullRequest
0 голосов
/ 04 мая 2018

Я написал компонент высокого порядка React / Typescript, чтобы разрешить отображение / скрытие компонентов на основе разрешений пользователя.

Работало отлично, пока я не попробовал это с ReactBootstrap NavDropdown. Нажатие обернутых MenuItems не закрывает меню.

Я понял, что пропеллер onSelected (примененный компонентом NavDropdown) не распространялся до MenuItem. Чтобы попытаться это исправить, я добавил код для ручного распространения реквизита вниз, но щелчок по-прежнему не закрывает меню.

Может кто-нибудь сказать мне, где я иду не так?

Обновление: при дальнейшем тестировании эта проблема вызывается даже переносом в React.Fragment.

Nav:

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 >;
  }
}

Wrapper:

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;
  }

}
...