⏳ Chapters
- Inspecting Our Layout's Prop Data
- Checking If Layout Is Already Set
- Creating Our AppLayout
- Using AppLayout As Our Default Layout
- Using A Different Layout from the Default
We'll inspect how Inertia injects our layout component and the data passed to it. We'll also learn how we can overwrite our default layout from our page components.
- Inspecting Our Layout's Prop Data
- Checking If Layout Is Already Set
- Creating Our AppLayout
- Using AppLayout As Our Default Layout
- Using A Different Layout from the Default
Hey Tom,
I was following along and got really stuck on this specific section, due to it being in React vs Vue:
For anyone who gets stuck adding different layouts from the default, you won't be able to follow it step by step using React. Instead, do this:
(PART 1)
export default function Login() { /* The Login page*/}
Login.layout = (page: ReactElement) => <AuthLayout children={page} />
Source: https://inertiajs.com/pages
(PART 2)
In your SSR/APP config, you would need to do something along the following:
resolve: (name) => {
const pages = import.meta.glob('../pages/**/*.tsx', { eager: true })
const resolvedPage = pages[`../pages/${name}.tsx`] as {
default: ComponentType & { layout?: (page: ReactElement) => ReactElement }
}
if (!resolvedPage.default.layout) {
resolvedPage.default.layout = (page) => <AppLayout>{page}</AppLayout>
}
return resolvedPage
},
(PART 3)
What the code above basically tells Inertia is this:
1 - Get the whole page itself
2 - Check if it is missing a layout.
3 - If it's missing a layout, wrap it around <AppLayout>, and go to step 4. (Skip if it's not missing a layout)
4 - Return the page for rendering
It keeps all the benefits of not GETing the resources all over again, and is very intuitive since you could add nest your layouts further like so:
https://inertiajs.com/pages#persistent-layouts (2nd example)
I spent the afternoon making it work with react.@inertiajs/react has a type called ResolvedComponent
(alias) type ResolvedComponent = ComponentType<any> & { layout?: LayoutComponent | LayoutComponent[] | LayoutFunction; } import ResolvedComponentCopied!
I imported ResolvedComponent and used it to type import.meta.glob in app.tsx and ssr.tsx. I then followed the code provided in the Inertia documentation to add a fallback to a default layout.
/// <reference path="../../adonisrc.ts" /> /// <reference path="../../config/inertia.ts" /> import '../css/app.css' import { hydrateRoot } from 'react-dom/client' import { createInertiaApp, type ResolvedComponent } from '@inertiajs/react' import { resolvePageComponent } from '@adonisjs/inertia/helpers' import { ReactNode } from 'react' import GuestLayout from '~/layouts/GuestLayout' const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS' createInertiaApp({ progress: { color: '#5468FF' }, title: (title) => `${title} - ${appName}`, resolve: async (name) => { const page = await resolvePageComponent( `../pages/${name}.tsx`, import.meta.glob<{ default: ResolvedComponent }>('../pages/**/*.tsx') ) page.default.layout = page.default.layout || ((page: ReactNode) => <GuestLayout children={page} />) return page }, setup({ el, App, props }) { hydrateRoot(el, <App {...props} />) }, })Copied!
import ReactDOMServer from 'react-dom/server' import { createInertiaApp, type ResolvedComponent } from '@inertiajs/react' import GuestLayout from '~/layouts/GuestLayout' import { ReactNode } from 'react' export default function render(page: any) { return createInertiaApp({ page, render: ReactDOMServer.renderToString, resolve: (name) => { const pages = import.meta.glob<{ default: ResolvedComponent }>('../pages/**/*.tsx', { eager: true, }) const page = pages[`../pages/${name}.tsx`] page.default.layout = page.default.layout || ((page: ReactNode) => <GuestLayout children={page} />) return page }, setup: ({ App, props }) => <App {...props} />, }) }Copied!
You can apply a layout of your choice to your pages like this:
import { ReactNode } from 'react' import { RegisterForm } from '~/components/register-form' import AuthLayout from '~/layouts/AuthLayout' export default function Register() { return ( <div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10"> <div className="w-full max-w-sm"> <RegisterForm /> </div> </div> ) } Register.layout = (page: ReactNode) => <AuthLayout children={page} />Copied!
Thank you for sharing, @gregory!! I'm happy to hear you were able to get it up and working with React!