使用 Next.js App Router 实现自定义 Material UI 主题

cyd*_*dev 5 javascript frontend reactjs material-ui next.js

长期从事 C# 开发,刚刚为客户启动 nextjs。

我用的是MUI,基本上一天的工作时间都在,所以我的项目很小。我对 SSR 在概念上的工作原理有很好的了解,但实现却让我陷入了一个奇怪的循环。

这是我的layout.js:

<!-- language:javascript -->
import "./globals.css";
import {
  Drawer,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  List,
  AppBar,
  Toolbar,
  Typography,
  Box,
} from "@mui/material";
import AssessmentIcon from "@mui/icons-material/Assessment";
import AddIcon from "@mui/icons-material/Add";
import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted";
import zIndex from "@mui/material/styles/zIndex";
import { theme } from "./theme";
import { ThemeProvider } from "@mui/material/styles";

const navItems = [
  { name: "Create New", icon: <AddIcon />, url: "todo" },
  { name: "View all", icon: <FormatListBulletedIcon />, url: "todo" },
  { name: "Dashboard", icon: <AssessmentIcon />, url: "todo" },
];

const getNav = () => {
  console.log(navItems);
  return (
    <List>
      {navItems.map((item, index) => (
        <ListItemButton className="navbutton" href={item.url} key={index}>
          <ListItemIcon>{item.icon}</ListItemIcon>
          <ListItemText>{item.name}</ListItemText>
        </ListItemButton>
      ))}
    </List>
  );
};

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <ThemeProvider theme={theme}>
          <AppBar position="relative" sx={{ zIndex: zIndex.drawer + 1 }}>
            <Toolbar>
              <Typography varient="h4">
                --client info--
              </Typography>
            </Toolbar>{" "}
          </AppBar>
          <Drawer anchor={"left"} variant="permanent">
            {getNav()}
          </Drawer>
          <main>{children}</main>
        </ThemeProvider>
      </body>
    </html>
  );
}

Run Code Online (Sandbox Code Playgroud)

和我友好的小 theme.js:

<!-- language:javascript -->
import { createTheme } from "@mui/material/styles";

export default theme = createTheme({
  typography: {
    allVariants: {
      fontFamily: "Trebuchet MS",
    },
  },
});
Run Code Online (Sandbox Code Playgroud)

我一直收到“错误:尝试从服务器调用 createTheme() 但 createTheme 在客户端上。不可能从服务器调用客户端函数,它只能呈现为组件或传递给客户端组件。

我真的不明白为什么在这里。我尝试了 UseEffect 和“use client”的一些变体;。

据我了解......这种字体应该呈现服务器端?正确的?我感觉我正在服用疯狂的药片。

提前致谢

尝试使用客户端语法,出现更多奇怪的错误,我认为从根本上来说这应该在服务器端呈现,我不明白错误的含义。

Sam*_*ore 4

服务器上发生的事情和客户端上发生的事情之间不匹配。如今,使用 Next.js App Router 可能会非常令人困惑,即使对于我们这些足够精通使用 Pages Router 的旧方法进行操作的人来说也是如此。

看起来您需要设置一个主题注册表,以便在正确的时间在正确的一侧调用各个部分。查看Material UI 文档中的Next.js App Router 指南,了解如何实现这一点。希望这可以帮助!

  • 如果您需要使用 Material UI + Next.js App Router 的空白入门项目,MUI 提供了此存储库:https://github.com/mui/material-ui/tree/master/examples/material-ui-nextjs-ts (5认同)
  • 仅供参考,您链接的项目使用较旧的 Pages Router 版本的 Next.js (12.1),而我链接的指南与导致原始问题的较新的 App Router 版本 (13.4+) 相关。因此,我不会说这个存储库“解决”了问题,而是通过降级来避免问题。 (2认同)