Building with AdonisJS & Inertia #2.7
Default Layouts & Overwriting the Default Layout
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.
- Created by
- @tomgobich
- Published
Join the Discussion 7 comments
-
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/pages3-
Responding to vladimir-laskin
(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
},
2-
Responding to vladimir-laskin
(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)2-
Responding to vladimir-laskin
-
Responding to vladimir-laskin
-
-
-
-
I spent the afternoon making it work with react.
@inertiajs/reacthas a type calledResolvedComponent(alias) type ResolvedComponent = ComponentType<any> & { layout?: LayoutComponent | LayoutComponent[] | LayoutFunction; } import ResolvedComponentCopied!I imported
ResolvedComponentand used it to typeimport.meta.globinapp.tsxandssr.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!1-
Responding to gregory
Thank you for sharing, @gregory!! I'm happy to hear you were able to get it up and working with React!
0
-