diff --git a/.changeset/large-chicken-obey.md b/.changeset/large-chicken-obey.md new file mode 100644 index 000000000000..307e2ddfb803 --- /dev/null +++ b/.changeset/large-chicken-obey.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: keep serialized remote data alive until navigation diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 4324606f28bf..32a8de1daea0 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -189,7 +189,10 @@ let target; /** @type {import('./types.js').SvelteKitApp} */ export let app; -/** @type {Record} */ +/** + * Data that was serialized during SSR. This is cleared when the user first navigates + * @type {Record} + */ export let remote_responses = {}; /** @type {Array<((url: URL) => boolean)>} */ @@ -240,7 +243,7 @@ let current = { /** this being true means we SSR'd */ let hydrated = false; -export let started = false; +let started = false; let autoscroll = true; let updating = false; let is_navigating = false; @@ -1488,6 +1491,8 @@ async function navigate({ block = noop, event }) { + remote_responses = {}; + const prev_token = token; token = nav_token; @@ -2096,6 +2101,8 @@ export function refreshAll({ includeLoadFunctions = true } = {}) { throw new Error('Cannot call refreshAll() on the server'); } + remote_responses = {}; + force_invalidation = true; return _invalidate(includeLoadFunctions, false); } diff --git a/packages/kit/src/runtime/client/remote-functions/form.svelte.js b/packages/kit/src/runtime/client/remote-functions/form.svelte.js index 7b831321d532..3eae1aff83dd 100644 --- a/packages/kit/src/runtime/client/remote-functions/form.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/form.svelte.js @@ -6,14 +6,7 @@ import { app_dir, base } from '$app/paths/internal/client'; import * as devalue from 'devalue'; import { DEV } from 'esm-env'; import { HttpError } from '@sveltejs/kit/internal'; -import { - app, - remote_responses, - started, - _goto, - set_nearest_error_page, - invalidateAll -} from '../client.js'; +import { app, remote_responses, _goto, set_nearest_error_page, invalidateAll } from '../client.js'; import { tick } from 'svelte'; import { refresh_queries, release_overrides } from './shared.svelte.js'; import { createAttachmentKey } from 'svelte/attachments'; @@ -42,7 +35,7 @@ export function form(id) { let issues = $state.raw({}); /** @type {any} */ - let result = $state.raw(started ? undefined : remote_responses[action_id]); + let result = $state.raw(remote_responses[action_id]); /** @type {number} */ let pending_count = $state(0); diff --git a/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js b/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js index 035bbf2693c3..ad00d2757276 100644 --- a/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/prerender.svelte.js @@ -3,7 +3,7 @@ import { app_dir, base } from '$app/paths/internal/client'; import { version } from '__sveltekit/environment'; import * as devalue from 'devalue'; import { DEV } from 'esm-env'; -import { app, remote_responses, started } from '../client.js'; +import { app, remote_responses } from '../client.js'; import { create_remote_function, remote_request } from './shared.svelte.js'; // Initialize Cache API for prerender functions @@ -117,11 +117,8 @@ class Prerender { export function prerender(id) { return create_remote_function(id, (cache_key, payload) => { return new Prerender(async () => { - if (!started) { - const result = remote_responses[cache_key]; - if (result) { - return result; - } + if (Object.hasOwn(remote_responses, cache_key)) { + return remote_responses[cache_key]; } const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`; diff --git a/packages/kit/src/runtime/client/remote-functions/query.svelte.js b/packages/kit/src/runtime/client/remote-functions/query.svelte.js index 4b1d5adad480..16af477581c8 100644 --- a/packages/kit/src/runtime/client/remote-functions/query.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/query.svelte.js @@ -1,7 +1,7 @@ /** @import { RemoteQueryFunction } from '@sveltejs/kit' */ /** @import { RemoteFunctionResponse } from 'types' */ import { app_dir, base } from '$app/paths/internal/client'; -import { app, goto, remote_responses, started } from '../client.js'; +import { app, goto, remote_responses } from '../client.js'; import { tick } from 'svelte'; import { create_remote_function, remote_request } from './shared.svelte.js'; import * as devalue from 'devalue'; @@ -14,11 +14,8 @@ import { HttpError, Redirect } from '@sveltejs/kit/internal'; export function query(id) { return create_remote_function(id, (cache_key, payload) => { return new Query(cache_key, async () => { - if (!started) { - const result = remote_responses[cache_key]; - if (result) { - return result; - } + if (Object.hasOwn(remote_responses, cache_key)) { + return remote_responses[cache_key]; } const url = `${base}/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`; @@ -38,11 +35,8 @@ export function query_batch(id) { return create_remote_function(id, (cache_key, payload) => { return new Query(cache_key, () => { - if (!started) { - const result = remote_responses[cache_key]; - if (result) { - return result; - } + if (Object.hasOwn(remote_responses, cache_key)) { + return remote_responses[cache_key]; } // Collect all the calls to the same query in the same macrotask, @@ -277,6 +271,7 @@ export class Query { * @returns {Promise} */ refresh() { + delete remote_responses[this._key]; return (this.#promise = this.#run()); }