Skip to content

Commit

Permalink
[core] Wrap App Router AppProvider in Suspense (#4526)
Browse files Browse the repository at this point in the history
  • Loading branch information
bharatkashyap authored Dec 11, 2024
1 parent f1de89a commit 5900e10
Show file tree
Hide file tree
Showing 11 changed files with 29 additions and 15 deletions.
15 changes: 11 additions & 4 deletions docs/data/toolpad/core/integrations/nextjs-approuter.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@ In your root layout file (for example, `app/layout.tsx`), wrap your application

```tsx title="app/layout.tsx"
import { AppProvider } from '@toolpad/core/AppProvider';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
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 }}>
<AppProvider navigation={NAVIGATION} branding={BRANDING}>
{children}
</AppProvider>
<React.Suspense fallback={<LinearProgress />}>
<AppProvider navigation={NAVIGATION} branding={BRANDING}>
{children}
</AppProvider>
</React.Suspense>
</AppRouterCacheProvider>
);
}
Expand All @@ -53,6 +56,10 @@ The `AppRouterCacheProvider` component is not required to use Toolpad Core, but
See the [Material UI Next.js integration docs](https://mui.com/material-ui/integrations/nextjs/) for more details.
:::

:::warning
If your app is statically rendered, you must wrap the `AppProvider` in a `Suspense` component when using the app router. See [https://github.com/mui/toolpad/issues/4524](https://github.com/mui/toolpad/issues/4524) for more information.
:::

## Create a dashboard layout

Create a layout file for your dashboard pages (for example, `app/(dashboard)/layout.tsx`):
Expand Down
2 changes: 1 addition & 1 deletion examples/core/auth-nextjs-email/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import type { Navigation } from '@toolpad/core';
Expand Down
2 changes: 1 addition & 1 deletion examples/core/auth-nextjs-passkey/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import type { Navigation } from '@toolpad/core';
Expand Down
2 changes: 1 addition & 1 deletion examples/core/auth-nextjs-themed/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import type { Navigation } from '@toolpad/core/AppProvider';
import { SessionProvider, signIn, signOut } from 'next-auth/react';
import theme from '../theme';
Expand Down
2 changes: 1 addition & 1 deletion examples/core/auth-nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import type { Navigation } from '@toolpad/core/AppProvider';
Expand Down
Empty file.
Empty file.
12 changes: 8 additions & 4 deletions examples/core/tutorial/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import type { Navigation } from '@toolpad/core/AppProvider';
import LinearProgress from '@mui/material/LinearProgress';
import theme from '../theme';

const NAVIGATION: Navigation = [
Expand All @@ -27,9 +29,11 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac
<html lang="en" data-toolpad-color-scheme="light">
<body>
<AppRouterCacheProvider options={{ enableCssLayer: true }}>
<AppProvider theme={theme} navigation={NAVIGATION}>
{children}
</AppProvider>
<React.Suspense fallback={<LinearProgress />}>
<AppProvider theme={theme} navigation={NAVIGATION}>
{children}
</AppProvider>
</React.Suspense>
</AppRouterCacheProvider>
</body>
</html>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ const rootLayout: Template = (options) => {

return `import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
${authEnabled ? '' : `import LinearProgress from '@mui/material/LinearProgress'`}
import type { Navigation } from '@toolpad/core/AppProvider';
${
authEnabled
Expand Down Expand Up @@ -57,6 +58,7 @@ export default ${authEnabled ? 'async ' : ''}function RootLayout(props: { childr
<body>
${authEnabled ? '<SessionProvider session={session}>' : ''}
<AppRouterCacheProvider options={{ enableCssLayer: true }}>
${authEnabled ? '' : '<React.Suspense fallback={<LinearProgress />}>'}
<AppProvider
navigation={NAVIGATION}
branding={BRANDING}
Expand All @@ -70,6 +72,7 @@ export default ${authEnabled ? 'async ' : ''}function RootLayout(props: { childr
>
{props.children}
</AppProvider>
${authEnabled ? '' : '</React.Suspense>'}
</AppRouterCacheProvider>
${authEnabled ? '</SessionProvider>' : ''}
</body>
Expand Down
2 changes: 1 addition & 1 deletion packages/toolpad-utils/src/react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function interleave(items: React.ReactNode[], separator: React.ReactNode)
for (let i = 0; i < items.length; i += 1) {
if (i > 0) {
if (ReactIs.isElement(separator)) {
result.push(React.cloneElement(separator, { key: `separator-${i}` }));
result.push(React.cloneElement(separator as React.ReactElement, { key: `separator-${i}` }));
} else {
result.push(separator);
}
Expand Down
2 changes: 1 addition & 1 deletion playground/nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { AppProvider } from '@toolpad/core/nextjs';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v14-appRouter';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v15-appRouter';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import type { Navigation } from '@toolpad/core/AppProvider';
Expand Down

0 comments on commit 5900e10

Please sign in to comment.