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