React-query 系列第 3 部分:使用 useQuery 钩子获取数据。
大家好👋
我又回来了。我一直很感激大家的鼓励。谢谢你们💖,谢谢你们抽出时间阅读这系列冗长的第二部分:QueryClient 配置。致我的新粉丝们:谢谢你们!我会尽力不让你们失望。
react-query
在第二部分中,我们讨论了如何通过为queries
和设置自定义默认值来覆盖 的一些默认设置。我们为和的mutations
等选项设置了retry
、staleTime
、cacheTime
以及refecthOnMount
其他一些自定义默认值。queries
retry
mutations
目录
简介
在本部分中,我们将学习如何使用钩子从 API 获取数据useQuery
。我之前承诺过会向您展示如何覆盖之前设置的默认值,所以我们也会讲解一下。请务必使用上面的目录跳转到与您相关的部分。
useQuery 钩子
我们首先安装axios并进行一些重构。
npm i axios
我们QueryClient
转到一个新文件./src/util/queryClient.js
import { QueryClient} from 'react-query';
const queryClientConfig = {
defaultOptions: {
queries: {
retry: 2,
staleTime: 1000 * 30,// 30 seconds
cacheTime: 1000 * 30, //30 seconds
refetchOnMount: "always",
refetchOnWindowFocus: "always",
refetchOnReconnect: "always",
refetchInterval: 1000 * 30, //30 seconds
refetchIntervalInBackground: false,
suspense: false,
},
mutations: {
retry: 2,
},
},
export const queryClient = new QueryClient(queryClientConfig);
如果你刚到这里,我们在这里解释了这个片段
我们App.js
因此清洁我们的
import { QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { queryClient } from "./util/queryClient";
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* The rest of your application */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
我们还将创建一个queryKeys.js
文件./src/util/queryKeys.js
。
此文件将托管我们应用程序的所有查询键。
export const fetchPostsKey = "FETCH_POSTS";
创建一个fetchPosts.service.js
文件,./src/services/fetchPosts.service.js
并创建一个简单的异步函数来获取帖子列表。
我们将在本演示中使用JSONPlaceholder REST API。
import axios from "axios";
/**
* @desc fetch a list of posts
*/
export const fetchPosts = async () => {
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`);
return res?.data;
};
获取数据
Posts.js
在以下位置创建组件./src/components/Posts.js
记得将你的Posts.js
组件导入到你的App.js
...
function App() {
return (
<QueryClientProvider client={queryClient}>
<Posts/>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
Posts.js
import { useQuery } from "react-query";
import { fetchPosts } from "../../services/fetchPosts.service";
import { fetchPostsKey } from "../../util/queryKeys";
const Posts = () => {
const { isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery(fetchPostsKey, fetchPosts);
return (
<div>
{isLoading ? (
<div>Loading...</div>
) : isError ? (
<div>An error while fetching posts</div>
) : (
data?.map((post) => (
<div key={post?.id}>
<div>{post?.title}</div>
<div>{post?.body}</div>
</div>
))
)}
</div>
);
};
export default Posts;
该useQuery
钩子接受查询键作为其第一个参数,并接受查询函数作为其第二个参数。查询键是必需的,查询函数也是必需的,因为in 中
没有定义默认查询函数。让我们快速浏览一下解构对象返回的内容。queries
QueryClient
useQuery
isLoading
:当查询没有数据且当前正在获取数据时boolean
返回的值,当没有数据时返回的值。true
false
isError
:也是一个值。当查询尝试导致错误时boolean
返回。true
isSuccess
:true
如果查询已收到无错误的响应并准备显示其数据,则返回。isSuccess
当false
查询尚未解决或导致错误时。
refetch
:这是一个手动重新获取查询的函数。
remove
:此功能用于手动从缓存中删除查询。
data
:这是上次成功查询的响应。如果第一次查询失败,data
则会返回。undefined
error
:这是查询的错误响应。当您的查询处于某种isError
状态时,它会被定义。
这个useQuery
钩子在解构对象中返回的值比这里描述的要多,但为了便于本文讨论,我选择了这几个。您可以在这里useQuery
阅读有关这个钩子的更多信息。
将变量传递给查询函数
那么,如果你想将一个或多个变量传递给查询函数,该怎么办呢?例如,你有一个函数,它只获取一篇帖子,并且要求你传入一个帖子id
;你该怎么做呢?
让我们看看怎么做。
queryKeys.js
我们将在 的文件中输入一个新的密钥./src/util/queryKeys.js
。
...
export const fetchSinglePostKey = "FETCH_SINGLE_POST";
还在 创建一个fetchSinglePost.service.js
文件./src/services/fetchSinglePost.service.js
并创建简单的异步函数来通过 获取单个帖子id
。
fetchSinglePost.service.js
import axios from "axios";
/**
* @desc fetches a single post
*/
export const fetchSinglePost = async ({queryKey}) => {
const [_key, id] = queryKey
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`);
return res?.data;
};
Post.js
import { useQuery } from "react-query";
import { fetchSinglePost } from "../../services/fetchSinglePost .service";
import { fetchSinglePostKey } from "../../util/queryKeys";
const Post = () => {
// fetching the post with the id of 1
const { isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery([fetchSinglePostKey, 1], fetchSinglePost );
return (
<div>
{isLoading ? (
<div>Loading...</div>
) : isError ? (
<div>An error while fetching post</div>
) : (
<div >
<div>{data?.title}</div>
<div>{data?.body}</div>
</div>
)
)}
</div>
);
};
export default Post;
在这里,我们不再使用string
值作为查询键,而是使用,首先传递查询字符串,然后根据查询函数的要求传递array
帖子。id
fetchSinglePost.service.js
fetchSinglePost
hook中声明的函数被useQuery
传入一个上下文,该上下文queryKey
array
嵌套在 hook 中。该queryKey
数组包含查询字符串(作为数组的第一项)以及id
用于获取单篇文章的变量。
记得将你的Post.js
组件导入到你的App.js
...
function App() {
return (
<QueryClientProvider client={queryClient}>
...
<Post/>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
覆盖查询默认值
我们已经看到了两个使用示例,useQuery
但别忘了,它们都是在queries
我们之前设置的默认值下运行的。为了覆盖某些全局配置,我们将一个对象作为第三个参数传递给useQuery
钩子。每个声明了新值的选项,只会在该useQuery
实例中被覆盖。
...
const { isLoading, isError, isSuccess, refetch, remove, data, error} = useQuery([fetchSinglePostKey, 1], fetchSinglePost, {
refetchInterval : 3* 1000 //3 seconds
});
...
上面这段代码的含义是,尽管我们react-query
全局配置为每 30 秒重新获取一次查询,但这个特定的查询将每 3 秒重新获取一次;脱离了全局配置。
结论
我们查询返回的数据会持久化到缓存中。下一部分,我们将讨论如何与缓存交互。
感谢大家的支持。如果您是初学者,还没有写过东西,那就赶紧写吧!如果这篇文章或其中一部分对您有帮助,请给我一个💖。也欢迎评论。
在推特上关注我@NnajioforEmma10