# react-query > 适用于 React Hooks 的请求库 > 远程数据的状态管理(也包括数据获取) 传统状态管理的缺点: 1. 远程数据无法控制 2. 需要写很多重复代码 3. 共享数据可能被修改 4. 数据可能过时 react-query的优点: 1. 缓存控制 2. 可以合并请求 3. 在后台更新过时数据 4. 知道数据什么时候过时 5. 分页和延迟加载等性能优化 6. 数据更新触发视图更新 7. 更好的内存回收 8. 存储更结构化并共享 ## 文档 1. 官方文档: https://tanstack.com/query/latest/docs/react/overview 2. 中文翻译: https://cangsdarm.github.io/react-query-web-i18n/react/ 3. 中文教程: https://juejin.cn/post/6937833844837974053 https://segmentfault.com/a/1190000041939135 ## 安装 ```bash pnpm add @tanstack/react-query ``` 兼容性: ``` Chrome >= 73 Firefox >= 78 Edge >= 79 Safari >= 12.0 iOS >= 12.0 opera >= 53 ``` ## 使用 三个重要概念: 查询, 修改, 主动查询失效 ### 查询 1. 实例化 queryClient 2. 用 QueryClientProvider 包裹 app ```tsx // main.tsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import { QueryClient, QueryClientProvider, } from '@tanstack/react-query' const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ) ``` 3. 用 useQuery 获取 异步数据 ```tsx /** * useQuery * - queryKey: 查询键, 是个数组, 通过不同的查询键来标识不同接口返回的不同数据, 简单理解成localstorage里的key * - key内的元素可以是嵌套数组、对象、字符串、数字 ['zen', { form: 'confucius' }] * - 从通用到特殊, 为了避免重复, 第一个可以是个字符串 * - 当key发生变化时, 会自动发起新的请求, 并缓存在新的key中 * - queryFn: 查询函数, 不只axios, fetch, 所有Promise都可以 * - 默认传参 {meta, pageParam, queryKey, signal} * - 返回: * - 状态只会是三种中的一种 * - isLoading: 加载状态 * - isError: 查询遇到一个错误 * - isSuccess: 查询成功,并且数据可用 * - data: 成功时的数据 * - error: 失败时的错误信息 */ ``` ```tsx import axios from 'axios' import { useQuery} from '@tanstack/react-query' type Props = {} const StusList = (props: Props) => { const getStudentsList = async (key:unknown)=>{ console.log('key:', key) try { const res = await axios.get('${window.apiUrl}/students') return res.data } catch (error) { if(error instanceof Error){ return error.message } } } const { isLoading, isError, data, error } = useQuery(['studentsList'], getStudentsList) return ( <> {isLoading && 数据正在加载中...} {data && {JSON.stringify(data)}} {isError && error instanceof Error && {error.message}} {/* error 默认类型为unknown, 运行时进行检查 */} ) } export default StusList ``` ### 并行查询 ```jsx import axios from 'axios' import { useState } from 'react' import { useQuery } from '@tanstack/react-query' const ParallelRequest = () => { const user1Query = useQuery(['stuInfo', 1], () => { return axios.get(`${window.apiUrl}/students/1`).then(res => res.data) }) const user2Query = useQuery(['stuInfo', 2], () => { return axios.get(`${window.apiUrl}/students/2`).then(res => res.data) }) const query = useQuery(['stuInfo', '1&2'], () => { return Promise.all([ axios.get(`${window.apiUrl}/students/1`).then(res => res.data), axios.get(`${window.apiUrl}/students/2`).then(res => res.data), ]) }) return (
先完成先展示: {user1Query.isLoading &&

用户1正在加载中...

} {user1Query.isError &&

用户1数据获取错误!

} {user1Query.data &&

用户1数据:{JSON.stringify(user1Query.data)}

} {user2Query.isLoading &&

用户2正在加载中...

} {user2Query.isError &&

用户2数据获取错误!

} {user2Query.data &&

用户2数据:{JSON.stringify(user2Query.data)}

}
全部完成再展示: {query.isLoading &&

正在加载中...

} {query.isError &&

请求错误!

} {query.data &&

{JSON.stringify(query.data)}

}
) } export default ParallelRequest ``` 第一部分 用户1, 用户2的数据, 谁先完成获取就展示谁 第二部分, 用户1 用户2全部获取完成后, 再进行展示, 在查询函数中使用了`Promise.all` ### 动态并行查询 > 查询数量在每次渲染时会发生变化, 不能使用手动查询, 使用`useQueries` 举例: 第一次查询`react, vue` 两个项目的仓库, 第二次查询 `selvte, ## Angular` 一个项目的仓库 ### 修改 ### 使查询失效 ```tsx ```