Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions packages/react/src/Deferred.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ const isSameUrlWithoutHash = (url1: URL | Location, url2: URL | Location): boole
}

interface DeferredProps {
children: ReactNode | (() => ReactNode)
fallback: ReactNode | (() => ReactNode)
children: ReactNode | ((props: { loading: boolean }) => ReactNode)
fallback?: ReactNode | (() => ReactNode)
data: string | string[]
}

Expand Down Expand Up @@ -47,11 +47,11 @@ const Deferred = ({ children, data, fallback }: DeferredProps) => {
setLoaded(keys.every((key) => pageProps[key] !== undefined))
}, [pageProps, keys])

if (loaded) {
return typeof children === 'function' ? children() : children
if (!loaded && fallback) {
return typeof fallback === 'function' ? fallback() : fallback
}

return typeof fallback === 'function' ? fallback() : fallback
return typeof children === 'function' ? children({ loading: !loaded }) : children
}

Deferred.displayName = 'InertiaDeferred'
Expand Down
26 changes: 26 additions & 0 deletions packages/react/test-app/Pages/DeferredProps/WithCallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Deferred, Link, usePage } from '@inertiajs/react'

const Foo = () => {
const { foo } = usePage<{ foo?: { text: string } }>().props

return foo?.text
}

const Bar = () => {
const { bar } = usePage<{ bar?: { text: string } }>().props

return bar?.text
}

export default () => {
return (
<>
<Deferred data="foo">{({ loading }) => (loading ? <div>Loading foo (callback)...</div> : <Foo />)}</Deferred>

<Deferred data="bar">{({ loading }) => (loading ? <div>Loading bar (callback)...</div> : <Bar />)}</Deferred>

<Link href="/deferred-props/page-1">Page 1</Link>
<Link href="/deferred-props/page-2">Page 2</Link>
</>
)
}
10 changes: 3 additions & 7 deletions packages/svelte/src/components/Deferred.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,10 @@
unsubscribe()
})
}

if (!$$slots.fallback) {
throw new Error('`<Deferred>` requires a `<svelte:fragment slot="fallback">` slot')
}
</script>

{#if loaded}
<slot />
{:else}
{#if !loaded && $$slots.fallback}
<slot name="fallback" />
{:else}
<slot loading={!loaded} />
{/if}
25 changes: 25 additions & 0 deletions packages/svelte/test-app/Pages/DeferredProps/WithCallback.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import { Deferred, inertia } from '@inertiajs/svelte'

export let foo: { text: string } | undefined
export let bar: { text: string } | undefined
</script>

<Deferred data="foo" let:loading>
{#if loading}
<div>Loading foo (callback)...</div>
{:else}
{foo?.text}
{/if}
</Deferred>

<Deferred data="bar" let:loading>
{#if loading}
<div>Loading bar (callback)...</div>
{:else}
{bar?.text}
{/if}
</Deferred>

<a href="/deferred-props/page-1" use:inertia>Page 1</a>
<a href="/deferred-props/page-2" use:inertia>Page 2</a>
7 changes: 4 additions & 3 deletions packages/vue3/src/deferred.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ export default defineComponent({
},
render() {
const keys = (Array.isArray(this.$props.data) ? this.$props.data : [this.$props.data]) as string[]
const loaded = keys.every((key) => this.$page.props[key] !== undefined)

if (!this.$slots.fallback) {
throw new Error('`<Deferred>` requires a `<template #fallback>` slot')
if (!loaded && this.$slots.fallback) {
return this.$slots.fallback()
}

return keys.every((key) => this.$page.props[key] !== undefined) ? this.$slots.default?.() : this.$slots.fallback()
return this.$slots.default?.({ loading: !loaded })
},
})
27 changes: 27 additions & 0 deletions packages/vue3/test-app/Pages/DeferredProps/WithCallback.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup lang="ts">
import { Deferred, Link } from '@inertiajs/vue3'

defineProps<{
foo?: { text: string }
bar?: { text: string }
}>()
</script>

<template>
<Deferred data="foo">
<template #default="{ loading }">
<div v-if="loading">Loading foo (callback)...</div>
<div v-else>{{ foo?.text }}</div>
</template>
</Deferred>

<Deferred data="bar">
<template #default="{ loading }">
<div v-if="loading">Loading bar (callback)...</div>
<div v-else>{{ bar?.text }}</div>
</template>
</Deferred>

<Link href="/deferred-props/page-1">Page 1</Link>
<Link href="/deferred-props/page-2">Page 2</Link>
</template>
6 changes: 3 additions & 3 deletions playgrounds/react/resources/js/Pages/Defer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ const Defer = ({
</div>

<div className="w-1/2 rounded-sm border border-gray-200 p-4">
{/* <Suspense fallback={<p>Loading Food...</p>}>
<DeferredFood />
</Suspense> */}
<Deferred data="users">
{({ loading }) => (loading ? <p>Loading Users (with callback)...</p> : <DeferredUsers />)}
</Deferred>
</div>

<div className="w-1/2 rounded-sm border border-gray-200 p-4">
Expand Down
14 changes: 14 additions & 0 deletions playgrounds/svelte4/resources/js/Pages/Defer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,20 @@
</div>
</Deferred>
</TestGridItem>

<TestGridItem>
<Deferred data="users" let:loading>
{#if loading}
<p>Loading Users (callback)...</p>
{:else}
<div>
{#each users as user (user.id)}
<p>#{user.id}: {user.name} ({user.email})</p>
{/each}
</div>
{/if}
</Deferred>
</TestGridItem>
</TestGrid>

<div class="mt-72">
Expand Down
11 changes: 11 additions & 0 deletions playgrounds/vue3/resources/js/Pages/Defer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ defineProps<{
</div>
</Deferred>
</TestGridItem>

<TestGridItem>
<Deferred data="users">
<template #default="{ loading }">
<p v-if="loading">Loading Users (with callback)...</p>
<div v-else v-for="user in users">
<p>#{{ user.id }}: {{ user.name }} ({{ user.email }})</p>
</div>
</template>
</Deferred>
</TestGridItem>
</TestGrid>

<div class="mt-72">
Expand Down
24 changes: 24 additions & 0 deletions tests/app/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,30 @@ app.get('/deferred-props/page-1', (req, res) => {
)
})

app.get('/deferred-props/with-callback', (req, res) => {
if (!req.headers['x-inertia-partial-data']) {
return inertia.render(req, res, {
component: 'DeferredProps/WithCallback',
deferredProps: {
default: ['foo', 'bar'],
},
props: {},
})
}

setTimeout(
() =>
inertia.render(req, res, {
component: 'DeferredProps/WithCallback',
props: {
foo: req.headers['x-inertia-partial-data']?.includes('foo') ? { text: 'foo value' } : undefined,
bar: req.headers['x-inertia-partial-data']?.includes('bar') ? { text: 'bar value' } : undefined,
},
}),
500,
)
})

app.get('/deferred-props/with-partial-reload/:mode', (req, res) => {
if (!req.headers['x-inertia-partial-data']) {
return inertia.render(req, res, {
Expand Down
14 changes: 14 additions & 0 deletions tests/deferred-props.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,17 @@ test('load deferred props with partial reload on mount', async ({ page }) => {
await expect(page.getByText('foo value')).toBeVisible()
await expect(page.getByText('bar value')).toBeVisible()
})

test('load deferred props with callback', async ({ page }) => {
await page.goto('/deferred-props/with-callback')

await expect(page.getByText('Loading foo (callback)...')).toBeVisible()
await expect(page.getByText('Loading bar (callback)...')).toBeVisible()

await page.waitForResponse(page.url())

await expect(page.getByText('Loading foo (callback)...')).not.toBeVisible()
await expect(page.getByText('Loading bar (callback)...')).not.toBeVisible()
await expect(page.getByText('foo value')).toBeVisible()
await expect(page.getByText('bar value')).toBeVisible()
})