2

いくつかの投稿や materail-ui Web サイトの例で言及されているように forwardRef を適用しましたが、コンソールにはまだ警告が表示されます。そして、私はその理由を本当に理解していません。

Material-UI リンク コンポーネントに埋め込まれた react-router リンクであるアイテムのリストを含むドロワーを作成しようとしています。私が作成したグローバル MUI テーマを活用するために、それらを埋め込んでいます。

PS : これは typescript コードです。Ref ストロングタイピングは地獄です ;-)

問題を再現する CODESANBOX はこちらです。ドロワーを表示するには、codesandbox ブラウザ ページを十分に拡張してください。

リンク コンポーネント

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