在 React Native (RN) 开发中,你是否也曾被这些问题困扰:
**满屏的
isLoading**:每个页面都要手写一遍 Loading 和 Error 逻辑。重复请求:切个页面回来,明明数据没变,却又发起了一次昂贵的网络请求。
数据不同步:在 A 页面改了用户信息,回到 B 页面还是旧数据。
手动缓存难:想做数据缓存,结果写了一堆 Redux 代码,维护起来像噩梦。
今天,我们要聊聊 **TanStack Query (原名 React Query)**。它被誉为 React 生态中“丢失的数据获取层”,能让你用最少的代码,解决最复杂的网络优化问题。
一、 为什么 RN 开发需要它?
很多人习惯把异步数据存在 Redux 或 Context 里。但本质上,Redux 是“全局状态管理”,而网络数据是“服务器状态”。
服务器状态具有以下特点:
离线存储:数据不在你的控制下,随时可能过期。
异步获取:需要通过异步 API 更新。
共享性:多个组件可能同时依赖同一份数据。
React Query 正是为管理服务器状态而生的“智囊团”。
二、 核心原理:它在幕后做了什么?
React Query 的核心是一套智能缓存机制。我们可以用“图书馆借书”来类比:
查询(Query):你向 React Query 索要数据。
缓存(Cache):它先看缓存里有没有。如果有且数据“新鲜(Fresh)”,直接给你,不发请求。
失效(Stale):如果数据“陈旧(Stale)”,它会在后台静默发起请求,同时先给你旧数据垫底(保证用户不看白屏)。
同步(Refetch):新数据回来后,自动替换缓存并通知组件重新渲染。
首先,我们在 App 入口处包裹QueryClientProvider。
2. 获取数据(useQuery)import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
export default function App() {
return (
QueryClientProvider>
);
}
告别useState+useEffect的繁琐,现在只需要一行代码:
3. 修改数据(useMutation)import { useQuery } from'@tanstack/react-query';
const fetchUser = async () => {
const res = await fetch('https://api.example.com/user');
return res.json();
};
function Profile() {
const { data, isLoading, isError, refetch } = useQuery({
queryKey: ['user'], // 缓存的唯一标识
queryFn: fetchUser, // 异步请求函数
});
if (isLoading) return;
if (isError) return;
return{data.name} Text>;
}
当你需要提交表单或删除数据时,使用useMutation:
四、 RN 专属优化进阶const mutation = useMutation({
mutationFn: updateUser,
onSuccess: () => {
// 关键点:数据改了,通知对应的缓存失效,触发自动刷新
queryClient.invalidateQueries({ queryKey: ['user'] });
},
});
在 React Native 中,有几个技巧能让你的应用丝滑到飞起:
1. 窗口聚焦重新获取 (Focus Refetching)
在 Web 端,切回标签页会自动刷新。在 RN 中,我们需要结合focusManager监听 App 状态:
2. 离线缓存import { focusManager } from '@tanstack/react-query';
import { AppState } from 'react-native';
focusManager.setEventListener((handleFocus) => {
const subscription = AppState.addEventListener('change', (status) => {
handleFocus(status === 'active');
});
return () => subscription.remove();
});
配合persistQueryClient,可以将数据持久化到AsyncStorage中。即使用户断网打开 App,也能瞬间看到上次缓存的数据。
3. 预加载 (Prefetching)
当用户划过列表项时,提前预加载详情页数据。用户点击进入时,详情页近乎“秒开”。
五、 总结:为什么要选它?
功能
传统方式 (useEffect)
React Query
缓存管理
手写内存缓存/Redux
自动管理,支持过期配置
数据同步
困难,需手动分发 Action
自动失效并重新获取
Loading状态
每个页面手写 useState
内置 isLoading, isFetching
性能
易产生多余渲染
深度优化,按需渲染
核心箴言:把复杂的状态同步交给 React Query,把简单的 UI 逻辑留给自己。
如果你正在开发一款对性能和体验有追求的 RN 应用,React Query 不是可选项,而是必选项。
六、 核心 API 深度解析:掌控数据流 1.useQuery:精细化查询
这是最常用的 Hook,但它的强大全在options配置里。
const { data } = useQuery({
queryKey: ['user', userId], // 1. 唯一标识,userId 变化会自动触发重新请求
queryFn: () => fetchUser(userId),
// --- 进阶配置 ---
staleTime: 1000 * 60 * 5, // 5分钟内数据被认为是“新鲜”的,不触发后台刷新
cacheTime: 1000 * 60 * 30, // 缓存保留30分钟,即使没有组件使用它
enabled: !!userId, // 只有当 userId 存在时才发起请求(串行请求利器)
retry: 3, // 失败后自动重试3次
select: (data) => data.user, // 数据过滤,组件只会在 data.user 变化时才重渲
});
Query Key 的重要性:React Query 的缓存是基于 Key 的。你可以把它想象成一个 Map 的 Key。数组里的值(如
userId)变化了,它就会被视为一个新的查询。
useMutation:副作用处理处理增删改操作,它的核心在于生命周期回调。
3.const mutation = useMutation({
mutationFn: (newTodo) => axios.post('/todos', newTodo),
onMutate: async (newTodo) => {
// 【高级技巧:乐观更新】
// 在请求发送前,手动修改缓存,让 UI 先变,如果失败再回滚
},
onSuccess: (data, variables, context) => {
// 操作成功后的动作,比如跳转页面
},
onError: (error, variables, context) => {
// 错误处理,比如弹出 Toast
},
onSettled: () => {
// 无论成功还是失败都会执行,类似 finally
}
});
QueryClient:全局指挥官queryClient不仅仅用于Provider,它还是你手动干预缓存的“手术刀”。
**
invalidateQueries**:暴力失效。告诉 React Query:“那个 Key 的数据旧了,去帮我重新拉一份。”**
setQueryData**:手动写缓存。不需要发请求,直接更新本地存的数据。**
getQueryData**:直接读取缓存中的数据(同步操作)。
在调试插件(DevTools)里,你会看到数据在不同状态间流转。理解这个闭环,你就理解了 React Query 的灵魂:
**Fresh (新鲜)**:数据是最新的,直接用,不发请求。
**Stale (陈旧)**:数据可用,但已经“过期”。你用它的同时,React Query 会悄悄在后台发请求同步。
**Fetching (获取中)**:正在网络传输。
**Inactive (非活跃)**:页面卸载了,数据暂时没人用,等着被垃圾回收(GC)。
不要在
queryFn里写逻辑:保持它纯净,只负责 fetch 数据。**合理设置
staleTime**:RN 应用通常不需要实时性极高。将staleTime设置为 1-2 分钟,能显著降低服务器压力并提升 App 流畅度。
好的,这份思维导图采用了 Markdown 格式,逻辑清晰,涵盖了从基础概念到进阶优化的所有重点。你可以直接将这段代码贴到支持 Markdown 的编辑器(如 Typora、Obsidian)中,或者直接作为公众号文章的总结大纲。
TanStack Query (React Query) 核心知识体系 1. 核心定位
本质:异步状态管理利器(Async State Manager)。
目标:将“服务器状态”与“客户端状态”分离。
RN 痛点解决:自动缓存、数据同步、离线支持、减少无效请求。
useQuery(读)queryKey: 缓存的唯一指纹(数组格式)。queryFn: 必须返回 Promise 的异步函数。staleTime: 数据从“新鲜”变“陈旧”的时间。cacheTime: 内存缓存保留时间(默认 5 分钟)。enabled: 控制请求开关(实现串行请求、按需请求)。useMutation(写)mutationFn: 处理 POST/PUT/DELETE。生命周期:
onMutate(乐观更新)、onSuccess、onError、onSettled。QueryClient(管)invalidateQueries: 主动标记缓存失效,触发静默刷新。setQueryData: 直接手动更新缓存内容。prefetchQuery: 预加载,提升页面切换速度。
Fresh (新鲜): 直接读取缓存,不触发网络请求。
Stale (陈旧): 先给缓存数据,同时后台静默发起请求同步。
Fetching (获取中): 正在进行网络请求。
Inactive (未激活): 组件已卸载,数据等待 GC(垃圾回收)。
Focus Refetch: 配合
AppState实现 App 切回前台时自动刷新。Online Manager: 监听网络状态,断网重连后自动重试。
Persistence: 结合
AsyncStorage实现数据离线持久化。
Select: 在 Hook 层进行数据过滤,减少组件不必要的重绘。
Placeholder Data: 使用占位数据(如旧数据)避免全屏 Loading。
Optimistic Updates: 乐观更新,让操作在网络返回前就完成 UI 变化。
React Query 的精髓不在于如何发起请求,而在于它如何通过一套优雅的协议,让开发者不再关心‘什么时候发请求’和‘怎么同步数据’。掌握了它,你的 RN 开发效率将提升一个量级。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.