Next.js - Material UI响应抽屉-修复页面更改时侧边栏/徽标的重新渲染

uklbhaso  于 2023-05-28  发布在  其他
关注(0)|答案(1)|浏览(105)

我正在Next.js项目中使用Material UI的responsive drawer
我注意到,每次我改变页面(点击侧边栏链接),标志消失和重新出现。
这是侧边栏的实现:

import ListAltIcon from "@mui/icons-material/ListAlt";
import SupervisorAccountIcon from "@mui/icons-material/SupervisorAccount";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import Drawer from "@mui/material/Drawer";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Toolbar from "@mui/material/Toolbar";

import Image from "next/image";
import logo from "../../../assets/logo.svg";
import kitten from "../../../assets/300.jpeg";

import { pages } from "../../../constants";

import StyledLink from "./sidebar.styled";

interface Props {
  handleDrawerToggle?: () => void;
  mobileOpen: boolean;
  drawerWidth: number;
}

const SidebarInner = () => (
  <div>
    <Toolbar>
      <Image
        src={logo}
        alt=" logo"
        width="120"
        height="64"
        className="logo-image"
        style={{ margin: "auto" }}
        priority={true}
      />
    </Toolbar>
    <Divider />
    <List sx={{ textDecoration: "none" }}>
      {Object.values(pages).map(({ name, url }, index) => (
        <ListItem key={url} disablePadding>
          <StyledLink href={url}>
            <ListItemButton>
              <ListItemIcon>
                {index % 2 === 0 ? <ListAltIcon /> : <SupervisorAccountIcon />}
              </ListItemIcon>
              <ListItemText primary={name} />
            </ListItemButton>
          </StyledLink>
        </ListItem>
      ))}
    </List>
    <Image src={kitten} alt="test image" style={{ margin: "auto" }} />
  </div>
);

export default function Sidebar(props: Props) {
  const { drawerWidth, handleDrawerToggle, mobileOpen } = props;

  return (
    <Box sx={{ display: "flex" }}>
      <Box
        component="nav"
        sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
        aria-label="mailbox folders"
      >
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Drawer
          variant="temporary"
          open={mobileOpen}
          onClose={handleDrawerToggle}
          ModalProps={{
            keepMounted: true, // Better open performance on mobile.
          }}
          sx={{
            display: { xs: "block", sm: "none" },
            "& .MuiDrawer-paper": {
              boxSizing: "border-box",
              width: drawerWidth,
            },
          }}
        >
          <SidebarInner />
        </Drawer>
        <Drawer
          variant="permanent"
          sx={{
            display: { xs: "none", sm: "block" },
            "& .MuiDrawer-paper": {
              boxSizing: "border-box",
              width: drawerWidth,
            },
          }}
          open
        >
          <SidebarInner />
        </Drawer>
      </Box>
    </Box>
  );
}

这是一个活的Sandbox
有没有人可以帮忙:

  • 理解为什么徽标重新渲染而下面的小猫没有重新渲染
  • 修复在链接更改过程中短时间消失的徽标
gj3fmq9x

gj3fmq9x1#

我分叉了沙盒存储库并修复了Sidebar.tsx组件中的问题,即:

import ListAltIcon from "@mui/icons-material/ListAlt";
import SupervisorAccountIcon from "@mui/icons-material/SupervisorAccount";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import Drawer from "@mui/material/Drawer";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Toolbar from "@mui/material/Toolbar";

import Image from "next/image";
import logo from "../../../assets/logo.svg";
import kitten from "../../../assets/300.jpeg";

import { pages } from "../../../constants";

import StyledLink from "./sidebar.styled";

interface Props {
  handleDrawerToggle?: () => void;
  mobileOpen: boolean;
  drawerWidth: number;
}

const svgIcon = () => {
  return (
    <svg width="280" height="80">
      <linearGradient id="lg">
        <stop offset="0%" stopColor="#33ff77" />
        <stop offset="100%" stopColor="#ff4444" />
      </linearGradient>
      <rect
        x="2"
        y="2"
        width="276"
        height="76"
        fill="red"
        stroke={"#555555"}
        strokeWidth={2}
      />
      <text
        x="50%"
        y="50%"
        fontSize="18"
        textAnchor="middle"
        alignmentBaseline="middle"
        fontFamily="monospace, sans-serif"
        fill="#555555"
      >
        280&#215;80
      </text>
    </svg>
  );
};

const SidebarInner = () => (
  <div>
    <Toolbar>
      {svgIcon()}
      <Image
        src={logo}
        alt=" logo"
        width="120"
        height="64"
        className="logo-image"
        style={{ margin: "auto" }}
        priority={true}
      />
    </Toolbar>
    <Divider />
    <List sx={{ textDecoration: "none" }}>
      {Object.values(pages).map(({ name, url }, index) => (
        <ListItem key={url} disablePadding>
          <StyledLink href={url}>
            <ListItemButton>
              <ListItemIcon>
                {index % 2 === 0 ? <ListAltIcon /> : <SupervisorAccountIcon />}
              </ListItemIcon>
              <ListItemText primary={name} />
            </ListItemButton>
          </StyledLink>
        </ListItem>
      ))}
    </List>
    <Image src={kitten} alt="test image" style={{ margin: "auto" }} />
  </div>
);

export default function Sidebar(props: Props) {
  const { drawerWidth, handleDrawerToggle, mobileOpen } = props;

  return (
    <Box sx={{ display: "flex" }}>
      <Box
        component="nav"
        sx={{ width: { sm: drawerWidth }, flexShrink: { sm: 0 } }}
        aria-label="mailbox folders"
      >
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Drawer
          variant="temporary"
          open={mobileOpen}
          onClose={handleDrawerToggle}
          ModalProps={{
            keepMounted: true, // Better open performance on mobile.
          }}
          sx={{
            display: { xs: "block", sm: "none" },
            "& .MuiDrawer-paper": {
              boxSizing: "border-box",
              width: drawerWidth,
            },
          }}
        >
          <SidebarInner />
        </Drawer>
        <Drawer
          variant="permanent"
          sx={{
            display: { xs: "none", sm: "block" },
            "& .MuiDrawer-paper": {
              boxSizing: "border-box",
              width: drawerWidth,
            },
          }}
          open
        >
          <SidebarInner />
        </Drawer>
      </Box>
    </Box>
  );
}

正如您所看到的,直接呈现的svg标记不会在页面更改时重新呈现,但是与next自己的<Image />标记一起使用的标记在页面更改时存在问题。
next/image导入的<Image />组件在仅重新呈现svg的文件时出现问题。建议在组件中直接使用svg文件。

相关问题