前端使用 React Query 管理“服務(wù)器狀態(tài)”的方法
一、安裝注冊(cè) react-query
首先要安裝 @tanstack/react-query:
npm install @tanstack/react-query
然后在入口文件中必須加 QueryClientProvider:
// main.tsx / index.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
const queryClient = new QueryClient();
export default function Root() {
return (
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
}二、使用 react-query
使用的 React Query 管理“服務(wù)器狀態(tài)”的步驟:
- 獲取數(shù)據(jù)(useQuery)
- 創(chuàng)建數(shù)據(jù)(useMutation)
- 更新與刪除
- 緩存、重新請(qǐng)求、樂觀更新
- 實(shí)戰(zhàn)項(xiàng)目文件結(jié)構(gòu)
【舉個(gè)例子】:
假設(shè)有一個(gè)服務(wù)器 API /api/todos?,F(xiàn)在需要你實(shí)現(xiàn)以下需求:
①、獲取 Todo 列表
②、新增 Todo
③、刪除 Todo
④、自動(dòng)刷新、緩存、錯(cuò)誤處理
1、定義獲取數(shù)據(jù)的查詢函數(shù) fetchTodos
// api/todoApi.ts
export const fetchTodos = async () => {
const res = await fetch('/api/todos');
if (!res.ok) throw new Error('Failed to fetch todos');
return res.json();
};
export const addTodo = async (title: string) => {
const res = await fetch('/api/todos', {
method: 'POST',
body: JSON.stringify({ title }),
headers: { 'Content-Type': 'application/json' }
});
if (!res.ok) throw new Error('Failed to add todo');
return res.json();
};
export const deleteTodo = async (id: number) => {
const res = await fetch(`/api/todos/${id}`, {
method: 'DELETE'
});
if (!res.ok) throw new Error('Failed to delete todo');
return res.json();
};2、使用 useQuery 獲取服務(wù)器狀態(tài)
import { useQuery } from '@tanstack/react-query';
import { fetchTodos } from './api/todoApi';
export function TodoList() {
const { data, isLoading, error } = useQuery({
queryKey: ['todos'], // 緩存 key(全局唯一)
queryFn: fetchTodos, // 請(qǐng)求函數(shù)
staleTime: 5000, // 5 秒內(nèi)不重新請(qǐng)求
refetchOnWindowFocus: false, // 切回窗口不重新請(qǐng)求
});
if (isLoading) return <div>加載中...</div>;
if (error) return <div>加載失敗</div>;
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}3、新增數(shù)據(jù)(useMutation + 自動(dòng)刷新列表)
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { addTodo } from './api/todoApi';
export function AddTodo() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (title: string) => addTodo(title),
onSuccess() {
// 手動(dòng)刷新 todos 列表
queryClient.invalidateQueries(['todos']);
},
});
const handleAdd = () => {
mutation.mutate('新的任務(wù)');
};
return (
<button onClick={handleAdd} disabled={mutation.isPending}>
{mutation.isPending ? '添加中...' : '添加 TODO'}
</button>
);
}4、刪除數(shù)據(jù)(useMutation + 樂觀更新)
React Query 的強(qiáng)大之處是:可以不用等服務(wù)器響應(yīng),先更新 UI,失敗再回滾:
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { deleteTodo } from './api/todoApi';
export function DeleteTodoButton({ id }) {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: () => deleteTodo(id),
// 樂觀更新
onMutate: async () => {
await queryClient.cancelQueries(['todos']);
const previousTodos = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], (old: any[]) =>
old.filter(todo => todo.id !== id)
);
return { previousTodos };
},
// 失敗時(shí)回滾
onError: (_err, _variables, context) => {
queryClient.setQueryData(['todos'], context.previousTodos);
},
// 成功后真正拉取最新數(shù)據(jù)
onSettled: () => {
queryClient.invalidateQueries(['todos']);
},
});
return (
<button onClick={() => mutation.mutate()}>
刪除
</button>
);
}5、組件組合
export default function App() {
return (
<div>
<h1>Todo 管理(React Query)</h1>
<AddTodo />
<TodoList />
</div>
);
}三、React Query 能做什么?不能做什么?
負(fù)責(zé)管理“服務(wù)器狀態(tài)”的難點(diǎn):
- 緩存
- 后臺(tái)刷新
- 自動(dòng)請(qǐng)求合并
- 樂觀更新
- 錯(cuò)誤恢復(fù)
- 對(duì)象引用穩(wěn)定性
- 重新請(qǐng)求策略
- 全局狀態(tài)同步
不處理:
- 本地 UI 狀態(tài)(modal 是否打開?)
- 表單狀態(tài)
- 跨組件 UI 狀態(tài)
?? 這些依然由 useState/useReducer/Zustand 來(lái)處理。
到此這篇關(guān)于前端使用 React Query 管理“服務(wù)器狀態(tài)”的文章就介紹到這了,更多相關(guān)React Query 服務(wù)器狀態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React學(xué)習(xí)之受控組件與數(shù)據(jù)共享實(shí)例分析
這篇文章主要介紹了React學(xué)習(xí)之受控組件與數(shù)據(jù)共享,結(jié)合實(shí)例形式分析了React受控組件與組件間數(shù)據(jù)共享相關(guān)原理與使用技巧,需要的朋友可以參考下2020-01-01
在React中如何優(yōu)雅的處理事件響應(yīng)詳解
這篇文章主要給大家介紹了關(guān)于在React中如何優(yōu)雅處理事件響應(yīng)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-07-07
react 權(quán)限樹形結(jié)構(gòu)實(shí)現(xiàn)代碼
這篇文章主要介紹了react 權(quán)限樹形結(jié)構(gòu)實(shí)現(xiàn)代碼,項(xiàng)目背景react + ant design,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-05-05
react時(shí)間分片實(shí)現(xiàn)流程詳解
實(shí)現(xiàn)react時(shí)間分片,主要內(nèi)容包括什么是時(shí)間分片、為什么需要時(shí)間分片、實(shí)現(xiàn)分片開啟 - 固定、實(shí)現(xiàn)分片中斷、重啟 - 連續(xù)、分片重啟、實(shí)現(xiàn)延遲執(zhí)行 - 有間隔、時(shí)間分片異步執(zhí)行方案的演進(jìn)、時(shí)間分片簡(jiǎn)單實(shí)現(xiàn)、總結(jié)、基本概念、基礎(chǔ)應(yīng)用、原理機(jī)制和需要注意的事項(xiàng)等2022-11-11
React?Native?中實(shí)現(xiàn)倒計(jì)時(shí)功能
這篇文章主要介紹了React?Native中實(shí)現(xiàn)倒計(jì)時(shí)功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

