inertiajs / inertia

Inertia.js lets you quickly build modern single-page React, Vue and Svelte apps using classic server-side routing and controllers.
https://inertiajs.com
MIT License
6.53k stars 433 forks source link

App.svelte is not being exported #1630

Open punyflash opened 1 year ago

punyflash commented 1 year ago

Version:

I want to declare a wrapper for global inertia's App component without rewriting it whole:

App.svelte

<script lang="ts">
    import Loading from "@/components/Loading.svelte";
    import Toast from "@/components/Toast.svelte";
    // import { App as InertiaApp } from "@inertiajs/svelte"
</script>

<!-- InertiaApp {...$$restProps} /-->
<Toast />
<Loading />

app.ts

import { createInertiaApp } from '@inertiajs/svelte';
import App from '@/App.svelte'
import '@/app.scss';

createInertiaApp({
    resolve: (name: string) => resolvePageComponent(
        `./pages/${name}.svelte`,
        import.meta.glob(`./pages/**/*.svelte`)
    ),
    setup({ el, props }) {
        const app = new App({ target: el, props, hydrate: true });
        delete el.dataset.page;

        return app
    }
})

For now, I required to use layout in every page component I create to populate toast and loading splash screen. It would be much easier if I could just wrap the whole inertia app within my custom component.

pedroborges commented 1 year ago

Hey @punyflash, I'd like to get the other maintainers opinion on the change your are proposing. cc/ @reinink @sebastiandedeyne @jessarcher @claudiodekker

At my company we define a default layout by using a custom page component resolver:

import { createInertiaApp } from '@inertiajs/svelte';
import App from '@/App.svelte'
import '@/app.scss';

import AppLayout from '@/layouts/App.svelte'

createInertiaApp({
    resolve: (name: string) => {
        const pages = import.meta.glob(`./pages/**/*.svelte`, { eager: true })
        const page = pages[`./pages/${name}.svelte`]

        if (typeof page === 'undefined') {
            throw new Error(`Page not found: "./pages/${name}.svelte"`)
        }

        return { ...page, layout: typeof page.layout === 'undefined' ? AppLayout : page.layout }
    },
    setup({ el, props }) {
        const app = new App({ target: el, props, hydrate: true });
        delete el.dataset.page;

        return app
    }
})

If a layout export is not defined on any page component it will use the one defined here.

punyflash commented 1 year ago

Hey, @pedroborges! In your case, layout will be just replaced in case some other is defined in the page component. But I'm showing the idea of wrapping it whole in some other custom component, so all layouts defined in the page component should work as well.

Though, it is doable in resolve method as well, but to be honest I feel like it's a bit hacky solution.