Svelte+TanStack Query:避免重复API调用及缓存取文章问题求助
问题解决方案
技术栈
- Svelte
- @tanstack/svelte-query
项目背景
现有两个页面:
posts/+page.svelte(文章列表页)post/[id]/[title]/+page.svelte(文章详情页)
基于Svelte开发,使用TanStack Query存储API数据,参考React文档(语法多数兼容)。
核心问题及修复方案
问题1:文章列表页重复触发API请求
每次导航到posts页面都会重新调用API,产生冗余请求。
修复思路
TanStack Query的缓存需要全局共享的QueryClient实例才能生效,同时通过配置缓存策略控制数据新鲜度,避免不必要的重新请求。
具体步骤
- 创建全局共享的QueryClient实例
在$lib/posts/queryClient.ts中定义全局QueryClient:
import { QueryClient } from '@tanstack/svelte-query'; export const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 3600000, // 1小时内数据视为"新鲜",不触发重新请求 cacheTime: 86400000, // 缓存保留24小时 refetchOnMount: false, // 组件挂载时不主动重新请求 refetchOnWindowFocus: false, // 窗口聚焦时不重新请求 }, }, });
- 在根布局中注入QueryClient
修改+layout.svelte,让所有页面共享同一个QueryClient:
<script> import { QueryClientProvider } from '@tanstack/svelte-query'; import { queryClient } from '$lib/posts/queryClient'; </script> <QueryClientProvider client={queryClient}> <slot /> </QueryClientProvider>
- 简化列表页代码
去掉不必要的store同步,直接使用Query的响应式数据:
<script lang="ts"> import { createQuery } from "@tanstack/svelte-query"; import type { Post } from "$lib/models/Post"; import { fetchPaginatedPosts } from "$lib/posts/fetch-pagination"; const query = createQuery({ queryKey: ["posts"], queryFn: fetchPaginatedPosts, }); let posts: Post[] = []; $: if ($query.data?.posts) { posts = $query.data.posts; } </script>
配置完成后,只要缓存数据在新鲜期内,导航回列表页就不会触发新的API请求。
问题2:详情页从缓存获取文章返回undefined
尝试从缓存获取单篇文章失败,返回undefined。
问题根源
- 创建了新的
QueryCache实例,无法访问全局QueryClient的缓存 find方法的语法错误(未传入回调函数)- 依赖
onMount而非响应式语句监听id变化
修复后的详情页代码
<script lang="ts"> import { page } from "$app/stores"; import type { Post } from "$lib/models/Post"; import { queryClient } from "$lib/posts/queryClient"; // 引入全局QueryClient let post: Post | undefined; // 响应式监听id变化,实时从缓存获取对应文章 $: { const id = $page.params.id; const cachedData = queryClient.getQueryData(["posts"]); if (cachedData?.posts) { post = cachedData.posts.find(item => item.id === id); console.log(post); } } </script>
关于你尝试的hooks.server.ts补充
如果需要在服务端预加载数据并填充缓存,可保留该代码,但注意:
- 服务端每次请求会创建新的QueryClient实例,缓存仅对当前请求有效
- 无需额外维护
fetchedPostsstore,直接通过全局QueryClient的缓存即可实现数据共享
内容的提问来源于stack exchange,提问作者kawa
相关产品推荐
相关产品推荐

