跳到主要內容
+

Next.js App Router

了解如何在 Next.js App Router 中使用 Joy UI。

範例

從新的基於 App Router 的專案開始?

透過這個範例:Joy UI - Next.js App Router with TypeScript,直接跳入程式碼。

Next.js 和 React Server Components

Next.js App Router 實作了 React Server Components,這是 React 即將推出的功能

為了支援 App Router,Joy UI 中需要存取瀏覽器 API 的元件和 Hook 都使用 "use client" 指令匯出。

在 App Router 中使用 Joy UI

若要設定 Joy UI,請建立一個自訂的 ThemeRegistry 元件,將 Emotion 的 CacheProvider、Joy UI 的 CssVarsProvidernext/navigation 中的 useServerInsertedHTML Hook 結合起來,如下所示

// app/ThemeRegistry.tsx
'use client';
import createCache from '@emotion/cache';
import { useServerInsertedHTML } from 'next/navigation';
import { CacheProvider } from '@emotion/react';
import { CssVarsProvider } from '@mui/joy/styles';
import CssBaseline from '@mui/joy/CssBaseline';
import theme from '/path/to/custom/theme'; // OPTIONAL

// This implementation is from emotion-js
// https://github.com/emotion-js/emotion/issues/2928#issuecomment-1319747902
export default function ThemeRegistry(props) {
  const { options, children } = props;

  const [{ cache, flush }] = React.useState(() => {
    const cache = createCache(options);
    cache.compat = true;
    const prevInsert = cache.insert;
    let inserted: string[] = [];
    cache.insert = (...args) => {
      const serialized = args[1];
      if (cache.inserted[serialized.name] === undefined) {
        inserted.push(serialized.name);
      }
      return prevInsert(...args);
    };
    const flush = () => {
      const prevInserted = inserted;
      inserted = [];
      return prevInserted;
    };
    return { cache, flush };
  });

  useServerInsertedHTML(() => {
    const names = flush();
    if (names.length === 0) {
      return null;
    }
    let styles = '';
    for (const name of names) {
      styles += cache.inserted[name];
    }
    return (
      <style
        key={cache.key}
        data-emotion={`${cache.key} ${names.join(' ')}`}
        dangerouslySetInnerHTML={{
          __html: styles,
        }}
      />
    );
  });

  return (
    <CacheProvider value={cache}>
      <CssVarsProvider theme={theme}>
        {/* the custom theme is optional */}
        <CssBaseline />
        {children}
      </CssVarsProvider>
    </CacheProvider>
  );
}

// app/layout.tsx
export default function RootLayout(props) {
  return (
    <html lang="en">
      <body>
        <ThemeRegistry options={{ key: 'joy' }}>{props.children}</ThemeRegistry>
      </body>
    </html>
  );
}

Props 序列化

從伺服器元件傳遞的 Props,例如 page.js 或其他路由檔案,必須是可序列化的