如何在NextJs(13.4)`/app` route中实现Material UI的`useMediaQuery`以避免flash?

ulmd4ohb  于 2023-06-22  发布在  其他
关注(0)|答案(1)|浏览(112)

我目前正在做一个Next.js项目,并利用'app'路由器来设置一个跨所有页面的通用布局。为了处理响应式设计,我使用了Material-UI(MUI)及其useMediaQuery钩子。然而,我遇到了一个问题,即在加载页面时,在渲染的最初几秒钟,桌面设备上会出现一个简短的闪屏。
下面是我的设置概述:
1.使用NextJS 13.4.4/app路由的MUI。
1.使用NextJS的"use client";指令。
代码如下:

"use client";
import { useState } from "react";
import { NextLinkComposed } from "../Link";
import { useTheme } from "@mui/material/styles";
import { drawerWidth } from "@/utils/constraints";
import {
  List,
  ListItem,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  Drawer,
  Box,
  useMediaQuery,
  InputAdornment,
  OutlinedInput,
} from "@mui/material";
import {
  GroupsOutlined as GroupsIcon,
  DashboardOutlined as DashboardIcon,
  Search as SearchIcon,
} from "@mui/icons-material";

export default function SideBar({
  handleDrawerToggle,
  drawerOpen,
}: {
  handleDrawerToggle: () => void;
  drawerOpen: boolean;
}) {
  const theme = useTheme();
  const matchUpMd = useMediaQuery(theme.breakpoints.up("md"));

  const container =
    typeof window !== undefined ? () => window.document.body : undefined;

  const [searchValue, setSearchValue] = useState("");

  const filteredItems = SideBarItems.filter((item) =>
    item.name.toLowerCase().includes(searchValue.toLowerCase())
  );

  const drawer = (
    <Box
      component="div"
      sx={{
        marginTop: { md: "66px", xs: "12px" },
        paddingLeft: "16px",
        paddingRight: "16px",
      }}
    >
      <Box>
        <OutlinedInput
          size="small"
          id="input-search-header"
          value={searchValue}
          onChange={(e) => setSearchValue(e.target.value)}
          sx={{
            borderRadius: 3,
          }}
          placeholder="Search"
          startAdornment={
            <InputAdornment position="start">
              <SearchIcon />
            </InputAdornment>
          }
          aria-describedby="search-helper-text"
          inputProps={{ "aria-label": "weight" }}
        />
      </Box>
      <List sx={{ marginTop: 2 }}>
        {filteredItems.map((item, index) => {
          const Icon = item.icon;
          return (
            <ListItem disablePadding key={index}>
              <ListItemButton
                sx={{ borderRadius: 3 }}
                component={NextLinkComposed}
                to={{
                  pathname: item.path,
                }}
              >
                <ListItemIcon>
                  <Icon />
                </ListItemIcon>
                <ListItemText primary={item.name} />
              </ListItemButton>
            </ListItem>
          );
        })}
      </List>
    </Box>
  );
  return (
    <Box
      component="nav"
      sx={{ flexShrink: { md: 0 }, width: matchUpMd ? drawerWidth : "auto" }}
      aria-label="mailbox folders"
    >
      <Drawer
        container={container}
        variant={matchUpMd ? "persistent" : "temporary"}
        open={drawerOpen}
        onClose={handleDrawerToggle}
        ModalProps={{
          keepMounted: true, // Better open performance on mobile.
        }}
        sx={{
          "& .MuiDrawer-paper": {
            width: drawerWidth,
            background: theme.palette.background.default,
            color: theme.palette.text.primary,
            borderRight: "none",
          },
        }}
      >
        {drawer}
      </Drawer>
    </Box>
  );
}

const SideBarItems = [
  {
    name: "Dashboard",
    path: "/dashboard",
    icon: DashboardIcon,
  },
  { name: "Users", path: "/user", icon: GroupsIcon },
];

请帮助!谢谢。

wgxvkvu9

wgxvkvu91#

你可以使用多个隐藏组件的方法,见这里。你可以创建两个单独的抽屉,并使用sx prop 将它们隐藏到断点处。

相关问题