2

尽管我已经应用了几篇文章和 materail-ui 网站示例中提到的 forwardRef,但我仍然在控制台中收到警告。我真的不明白为什么。

我正在尝试创建一个包含项目列表的抽屉,这些项目是嵌入到 Material-UI 链接组件中的反应路由器链接。我嵌入它们是为了从我创建的全局 MUI 主题中受益

PS:这是一个打字稿代码。参考强类型是地狱;-)

这是重现问题的 CODESANBOX。确保扩展足够的代码框浏览器页面以显示抽屉

链接组件

import { Link as MUILink, LinkBaseProps } from "@material-ui/core";
import React from "react";
import {
  Link as LinkRouter,
  LinkProps as RouterLinkProps
} from "react-router-dom";

type RefLinkRouter =
  | ((instance: HTMLAnchorElement | null) => void)
  | React.RefObject<HTMLAnchorElement>
  | null
  | undefined;

type ILinkProps = RouterLinkProps;

const fwdLink = (props: ILinkProps, ref: RefLinkRouter): JSX.Element => (
  <LinkRouter ref={ref} {...props} />
);
const ForwardedLink = React.forwardRef<HTMLAnchorElement | null, ILinkProps>(
  fwdLink
);

const Link: React.FC<ILinkProps & LinkBaseProps> = (
  props: ILinkProps & LinkBaseProps
) => {
  return (
    <MUILink component={ForwardedLink} to={props.to} {...props}>
      {props.children}
    </MUILink>
  );
};

export { Link, ILinkProps };

抽屉组件

import { Link } from "./../Link";
import { List, ListItem, makeStyles } from "@material-ui/core";
import Drawer from "@material-ui/core/Drawer";
import Hidden from "@material-ui/core/Hidden";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import MailIcon from "@material-ui/icons/Mail";
import InboxIcon from "@material-ui/icons/MoveToInbox";
import React from "react";

const drawerWidth = 240;

interface IOptionsValue {
  value: string;
  label: string;
}

interface IDrawerMenuItemsProps extends IOptionsValue {
  to: string;
  iconName?: JSX.Element;
}

interface IResponsiveDrawerProps {
  container?: number;
  menuItems: Array<IDrawerMenuItemsProps>;
}

const useStyles = makeStyles({
  list: {
    backgroundColor: "blue"
  },
  drawerMenuItemList: {
    color: "white",
    backgroundColor: "blue"
  }
});

const ResponsiveDrawer: React.FC<IResponsiveDrawerProps> = (
  props: IResponsiveDrawerProps
): JSX.Element => {
  // const { container } = props;
  const { menuItems } = props;

  const classes = useStyles();
  const [mobileOpen, setMobileOpen] = React.useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const drawer = (
    <div>
      <div />
      <List className={classes.drawerMenuItemList}>
        {menuItems.map((menuItem: IDrawerMenuItemsProps, index: number) => {
          return (
            <ListItem
              className={classes.drawerMenuItemList}
              key={menuItem.value}
              component={Link}
              to={menuItem.to}
            >
              <ListItemIcon className={classes.drawerMenuItemList}>
                {index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
              </ListItemIcon>
              <p className={classes.drawerMenuItemList}>{menuItem.label}</p>
            </ListItem>
          );
        })}
      </List>
    </div>
  );

  return (
    <>
      <Hidden smUp implementation="css">
        <Drawer
          //                    container={container}
          style={{ width: drawerWidth }}
          variant="temporary"
          anchor={"right"}
          open={mobileOpen}
          onClose={handleDrawerToggle}
          ModalProps={{
            keepMounted: true // Better open performance on mobile.
          }}
        >
          {drawer}
        </Drawer>
      </Hidden>
      <Hidden xsDown implementation="css">
        <Drawer variant="permanent" open>
          {drawer}
        </Drawer>
      </Hidden>
    </>
  );
};

export default ResponsiveDrawer;

我称之为抽屉的主页

import React from "react";
import ResponsiveDrawer from "./../ResponsiveDrawer";

const HomePage = () => {
  const menuItems = [
    {
      label: "Menu 1",
      value: "menu1",
      to: "/app"
    },
    {
      label: "Menu 2",
      value: "menu2",
      to: "/app"
    }
  ];

  return (
    <>
      <ResponsiveDrawer menuItems={menuItems} />
      <div>here were are</div>
    </>
  );
};

export default HomePage;

在此处输入图像描述

4

1 回答 1

3

根据文档,我们对使用 Refs 有一些注意事项。

https://material-ui.com/guides/composition/#caveat-with-refs

但是,您实现它的方式,我意识到您的想法是利用 Material-UI 的 Link 组件,该组件具有 react-router 的能力并使用 Children 组件。

在这种情况下,您可以使用“组件”属性,但为此您必须使用 React.forwardRef 来转发 ref 以使组件能够访问 DOM 节点。

https://codesandbox.io/s/keen-banzai-o2q24

    type LinkProps = LinkBaseProps & RouterLinkProps;

    const LinkBehavior = React.forwardRef<any, ILinkProps>((props, ref) => (
       <MUILink component={LinkRouter} ref={ref} to={props.to} {...props} />
    ));

    export { LinkBehavior as Link };
    export type ILinkProps = LinkProps;
于 2020-04-26T21:34:08.950 回答