跳到内容
+

Next.js App Router

本指南将引导你完成将 Toolpad Core 添加到现有 Next.js 应用程序的过程。

先决条件

确保你已安装 @mui/materialnext。你还需要以下工具才能使集成正常工作

npm install @mui/material-nextjs @emotion/cache

使用 NextAppProvider 包裹你的应用程序

在你的根布局文件(例如,app/layout.tsx)中,使用 NextAppProvider 包裹你的应用程序

app/layout.tsx
import { NextAppProvider } from '@toolpad/core/nextjs';
import LinearProgress from '@mui/material/LinearProgress';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <AppRouterCacheProvider options={{ enableCssLayer: true }}>
      <React.Suspense fallback={<LinearProgress />}>
        <NextAppProvider navigation={NAVIGATION} branding={BRANDING}>
          {children}
        </NextAppProvider>
      </React.Suspense>
    </AppRouterCacheProvider>
  );
}

你可以在 AppProvider 页面上找到有关 NextAppProvider props 的详细信息。

创建一个仪表盘布局

为你的仪表盘页面创建一个布局文件(例如,app/(dashboard)/layout.tsx

app/(dashboard)/layout.tsx
import * as React from 'react';
import { DashboardLayout } from '@toolpad/core/DashboardLayout';
import { PageContainer } from '@toolpad/core/PageContainer';

export default function DashboardPagesLayout(props: { children: React.ReactNode }) {
  return (
    <DashboardLayout>
      <PageContainer>{props.children}</PageContainer>
    </DashboardLayout>
  );
}

DashboardLayout 组件为你的仪表盘页面提供一致的布局,包括侧边栏、导航和标题。PageContainer 组件用于包裹页面内容,并为导航提供面包屑。

创建一个仪表盘页面

现在你可以在仪表盘中创建页面。例如,一个主页 (app/(dashboard)/page.tsx)

app/(dashboard)/page.tsx
import * as React from 'react';
import Typography from '@mui/material/Typography';

export default function Page() {
  return <Typography>Welcome to a page in the dashboard!</Typography>;
}

就是这样!你现在已将 Toolpad Core 集成到你的 Next.js 应用程序中。

(可选)添加第二个页面

在仪表盘中创建一个新页面,例如,app/(dashboard)/orders/page.tsx

app/(dashboard)/orders/page.tsx
import * as React from 'react';
import Typography from '@mui/material/Typography';

export default function OrdersPage() {
  return <Typography>Welcome to the orders page!</Typography>;
}

要将此页面添加到导航,请将其添加到 NAVIGATION 变量

app/layout.tsx
export const NAVIGATION = [
  // ...
  {
    segment: 'orders',
    title: 'Orders',
    icon: <ShoppingCartIcon />,
  },
  // ...
];

(可选)设置身份验证

如果你想添加身份验证,你可以将 Auth.js 与 Toolpad Core 一起使用。这是一个示例设置

安装依赖项

npm install next-auth@beta

创建一个 auth.ts 文件

auth.ts
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import type { Provider } from 'next-auth/providers';

const providers: Provider[] = [
  GitHub({
    clientId: process.env.GITHUB_CLIENT_ID,
    clientSecret: process.env.GITHUB_CLIENT_SECRET,
  }),
];

export const providerMap = providers.map((provider) => {
  if (typeof provider === 'function') {
    const providerData = provider();
    return { id: providerData.id, name: providerData.name };
  }
  return { id: provider.id, name: provider.name };
});

export const { handlers, auth, signIn, signOut } = NextAuth({
  providers,
  secret: process.env.AUTH_SECRET,
  pages: {
    signIn: '/auth/signin',
  },
  callbacks: {
    authorized({ auth: session, request: { nextUrl } }) {
      const isLoggedIn = !!session?.user;
      const isPublicPage = nextUrl.pathname.startsWith('/public');

      if (isPublicPage || isLoggedIn) {
        return true;
      }

      return false; // Redirect unauthenticated users to login page
    },
  },
});

创建一个登录页面

使用 SignInPage 组件向你的应用程序添加登录页面。例如,app/auth/signin/page.tsx

app/auth/signin/page.tsx
import * as React from 'react';
import { SignInPage, type AuthProvider } from '@toolpad/core/SignInPage';
import { AuthError } from 'next-auth';
import { providerMap, signIn } from '../../../auth';

export default function SignIn() {
  return (
    <SignInPage
      providers={providerMap}
      signIn={async (
        provider: AuthProvider,
        formData: FormData,
        callbackUrl?: string,
      ) => {
        'use server';
        try {
          return await signIn(provider.id, {
            redirectTo: callbackUrl ?? '/',
          });
        } catch (error) {
          // The desired flow for successful sign in in all cases
          // and unsuccessful sign in for OAuth providers will cause a `redirect`,
          // and `redirect` is a throwing function, so we need to re-throw
          // to allow the redirect to happen
          // Source: https://github.com/vercel/next.js/issues/49298#issuecomment-1542055642
          // Detect a `NEXT_REDIRECT` error and re-throw it
          if (error instanceof Error && error.message === 'NEXT_REDIRECT') {
            throw error;
          }
          // Handle Auth.js errors
          if (error instanceof AuthError) {
            return {
              error: error.message,
              type: error.type,
            };
          }
          // An error boundary must exist to handle unknown errors
          return {
            error: 'Something went wrong.',
            type: 'UnknownError',
          };
        }
      }}
    />
  );
}

为登录创建一个路由处理程序

next-auth 需要一个用于登录的路由处理程序。创建一个文件 app/api/auth/[...nextauth]/route.ts

app/api/auth/[...nextauth]/route.ts
import { handlers } from '../../../../auth';

export const { GET, POST } = handlers;

添加中间件

向你的应用程序添加中间件以保护你的仪表盘页面

middleware.ts
export { auth as middleware } from './auth';

export const config = {
  // https://nextjs.net.cn/docs/app/building-your-application/routing/middleware#matcher
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};

就是这样!你现在已将 Toolpad Core 集成到具有身份验证设置的 Next.js App Router 应用程序中

Next.js App Router with Toolpad Core

带有 Toolpad Core 的 Next.js App Router