译零 TransZero · TanStack Query v4 中文文档
主站

SSR 和 SvelteKit

设置

SvelteKit 默认将在 SSR 编译阶段渲染路由。 出于这一点考虑,你需要在服务器端禁用查询,否则你的查询将在服务器端没有 HTML 内容的情况下异步运行(HTML 已被送至客户端)。

推荐的解决办法是在QueryClient实例中导入 SvelteKit 的browser模块。 这并不会禁用queryClient.prefetchQuery(),因为它涉及到如何预取数据:

src/routes/+layout.svelte

Markdown
1<script lang="ts">2  import { browser } from '$app/environment'3  import { QueryClient, QueryClientProvider } from '@tanstack/svelte-query'4 5  const queryClient = new QueryClient({6    defaultOptions: {7      queries: {8        enabled: browser,9      },10    },11  })12</script>1314<QueryClientProvider client={queryClient}>15  <slot />16</QueryClientProvider>

预取数据

Svelte Query 支持两种将服务器端预取的数据传输到客户端的方法。

如果你希望有更为详尽的解释,希望有点代码可用,请查看 SSR 的入门例子.

使用 initialData

组合 SvelteKit 的 load特性,你可以将预取的数据在服务器端传输给createQuery的initialData选项:

src/routes/+page.ts

TypeScript
1import type { PageLoad } from "./$types";2 3export const load: PageLoad = async () => {4  const posts = await getPosts();5  return { posts };6};

src/routes/+page.svelte

Markdown
1<script>2  import { createQuery } from '@tanstack/svelte-query'3  import type { PageData } from './$types'4 5  export let data: PageData6 7  const query = createQuery({8    queryKey: ['posts'],9    queryFn: getPosts,10    initialData: data.posts11  })12</script>

优点:

  • 这种方式是最小化的,且这是对于常用场景的最快的方法
  • 和+page.ts/+layout.ts以及+page.server.ts/+layout.server.ts的 load 函数无任何冲突

缺点:

  • 如果你在组件树的某个组件调用createQuery函数,你必须将initialData透传过去
  • 如果你通过createQuery创建的查询在多个地方被调用,你必须将initialData透传给每一个查询
  • 查询在服务器端预取的准确时间是无法获知的,所以dataUpdatedAt和其他关于重新获取的逻辑都依赖于页面何时被加载

使用 prefetchQuery

Svelte Query 支持在服务器端通过查询预取数据。 使用下面的设置,你可以早在数据送到客户端之前提前查询。 因此,这些数据已被标记为缓存对象,不能从客户端初始化:

src/routes/+layout.ts

TypeScript
1import { browser } from "$app/environment";2import { QueryClient } from "@tanstack/svelte-query";3import type { LayoutLoad } from "./$types";4 5export const load: LayoutLoad = async () => {6  const queryClient = new QueryClient({7    defaultOptions: {8      queries: {9        enabled: browser,10      },11    },12  });13 14  return { queryClient };15};

src/routes/+layout.svelte

Markdown
1<script lang="ts">2  import { QueryClientProvider } from '@tanstack/svelte-query'3  import type { LayoutData } from './$types'4 5  export let data: LayoutData6</script>7 8<QueryClientProvider client={data.queryClient}>9  <slot />10</QueryClientProvider>

src/routes/+page.ts

TypeScript
1import type { PageLoad } from "./$types";2 3export const load: PageLoad = async ({ parent, fetch }) => {4  const { queryClient } = await parent();5 6  // 你需要使用 SvelteKit 的 fetch 函数7  await queryClient.prefetchQuery({8    queryKey: ["posts"],9    queryFn: async () => (await fetch("/api/posts")).json(),10  });11};

src/routes/+page.svelte

Markdown
1<script lang="ts">2  import { createQuery } from '@tanstack/svelte-query'3 4  // 这个数据被 prefetchQuery 缓存在 +page.ts 里,所以(客户端)没有任何真实的查询被触发5  const query = createQuery({6    queryKey: ['posts'],7    queryFn: async () => (await fetch('/api/posts')).json(),8  })9</script>

优点:

  • 服务器端的数据不需要任何形式的透传,可以被任何地方随意访问
  • 在客户端页面渲染时没有初始化请求负载,因为缓存已经知悉了所有有关查询的信息,包括dataUpdatedAt

缺点:

  • 需要更为复杂的设置
  • 无法和 +page.server.ts/+layout.server.ts 的 load 函数一起使用 (并且,无论如何,与 Svelte Query 一起使用的 API 都需要完全暴露给浏览器)

本页为 TanStack Query 文档(Svelte 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

本页译文取自社区中文版 react-query-web-i18n(MIT),非本站翻译,已停止更新,内容可能与当前 API 有出入。

译自上游 (未记录版本)