react 查询节流
One of the challenges we face when building an application with React is determining a code pattern for fetching data from the server. The most common way to handle data fetching in React is to use the global state as a mechanism to determine the current status of the fetch operation.
在使用React构建应用程序时,我们面临的挑战之一是确定用于从服务器获取数据的代码模式。 在React中处理数据获取的最常见方法是使用全局状态作为一种机制来确定获取操作的当前状态。
Here is an example of fetching data from Star Wars API:
以下是从《星球大战》 API获取数据的示例:
import React, {useState, useEffect} from 'react';
import axios from 'axios';// regular fetch with axios
function App() {
const [isLoading, setLoading] = useState(false)
const [isError, setError] = useState(false)
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async () => {
setError(false);
setLoading(true);
try {
const response = await axios('http://swapi.dev/api/people/1/');
setData(response.data);
} catch (error) {
setError(true);
}
setLoading(false);
};
fetchData()
}, []);return (
<div className="App">
<h1>React Query example with Star Wars API</h1>
{isError && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Loading ...</div>
) : (
<pre>{JSON.stringify(data, null, 2)}
</pre>
)}
</div>
);
}export default App;
The code above requires both useState
and useEffect
hooks and uses three different states to store data and determine whether the application is fetching data or already has an error response from the API. This pattern is repeated over and over again for most of your application data fetching logic.
上面的代码同时需要useState
和useEffect
钩子,并使用三种不同的状态来存储数据并确定应用程序是在获取数据还是已经从API获得错误响应。 对于大多数应用程序数据获取逻辑,将反复重复此模式。
And that’s not all. The most common problems with data fetching in React includes:
不仅如此。 React中数据获取的最常见问题包括:
- Data is shared across all app instance and can be changed by other people 数据在所有应用程序实例之间共享,并且可以由其他人更改
- Data could be “stale” and needs to be refreshed 数据可能是“过时的”,需要刷新
- Handle caching and invalidating data to optimize the request operation 处理缓存和使数据无效以优化请求操作
Finally, there is also the problem of having the local state which commonly stores your user’s preferences like theme and sidebar config coupled with the remote state which holds the data fetched from API:
最后,还有一个问题是,本地状态通常存储用户的首选项(例如主题和侧边栏配置),而远程状态则存储从API获取的数据:
//what global state commonly look like nowadays
const state = {
theme: "light",
sidebar: "off",
followers: [],
following: [],
userProfile: {},
messages:[],
todos:[],
}
Wouldn’t it be nice if you could separate the local state from the remote state? And what if you can reduce the amount of boilerplate code you need to write for data fetching?
如果您可以将本地状态与远程状态分开,那不是很好吗? 而且,如果可以减少为获取数据而需要编写的样板代码量呢?
One solution would be to create your own custom hook to handle fetching and handling of data. That’s a completely valid solution. You can also share and manage this hook in a component hub like Bit (Github). This way you’ll have it available for any project you’re working on (it can be as a pure hook but also as part of other reusable “smart components”).
一种解决方案是创建您自己的自定义钩子,以处理数据的获取和处理。 那是一个完全有效的解决方案。 您还可以在类似Bit ( Github )的组件中心中共享和管理此钩子。 这样,您就可以将其用于正在处理的任何项目(它可以作为纯钩子使用,也可以作为其他可重复使用的“智能组件”的一部分)。
Another solution and one that we’ll be exploring here in-depth is React Query. This library will help you to fetch, synchronize, update, and cache your remote data while also reducing the amount of code you need to write by providing you two simple hooks and one utility function.
我们将在这里深入探讨的另一个解决方案是React Query 。 该库将为您提供两个简单的钩子和一个实用程序功能,从而帮助您获取,同步,更新和缓存远程数据,同时还减少了您需要编写的代码量。
To get the most out of this article, please download this sample repo that I’ve modified from the author:
为了从本文中获得最大收益,请下载我从作者那里修改过的这个示例仓库 :
This small React app will retrieve an array of strings from the API route using axios. You can put a new string into the array by using the provided form. It also has the React Query DevTools opened so you can see the cached data in real-time.
这个小型的React应用程序将使用axios从API路由中检索字符串数组。 您可以使用提供的表格将新字符串放入数组中。 它还打开了React Query DevTools,因此您可以实时查看缓存的数据。
useQuery
挂钩 (The useQuery
hook)
The useQuery
hook is a function used to register your data fetching code into React Query library. It takes an arbitrary key and an asynchronous function for fetching data and return various values that you can use to inform your users about the current application state.
useQuery
钩子是用于将数据获取代码注册到React Query库中的功能。 它需要一个任意键和一个异步函数来获取数据并返回各种值,您可以使用这些值来通知用户有关当前应用程序状态。
For example, let’s refactor the Star Wars API example above:
例如,让我们重构上面的《星球大战》 API示例:
import React from 'react';
import axios from 'axios';
import {useQuery} from 'react-query';// react-query fetch with axios
function App() {
const { isLoading, error, data } = useQuery('fetchLuke', () =>
axios('http://swapi.dev/api/people/1/'))return (
<div className="App">
<h1>React Query example with star wars API</h1>
{error && <div>Something went wrong ...</div>}
{isLoading ? (
<div>Retrieving Luke Skywalker Information ...</div>
) : (
<pre>{JSON.stringify(data, null, 2)}
</pre>
)}
</div>
);
}export default App;
Notice how in this code, we aren’t using the regular useState
and useEffect
hooks. This is because useQuery
already has various values that we can use inside the application, such as isLoading
, error
response, and returned data
.
请注意,在这段代码中,我们没有使用常规的useState
和useEffect
挂钩。 这是因为useQuery
已经具有可在应用程序内部使用的各种值 ,例如isLoading
, error
响应和返回的data
。
Back to the sample repo, you can see how I fetched the todo list from the api by using the same useQuery
function inside /pages/index.js
:
回到样品回购,你可以看到我是如何获取从API的待办事项列表使用相同的useQuery
内部功能/pages/index.js
:
const { status, data, error, isFetching } = useQuery('todos', async () => {
const { data } = await axios.get('/api/data')
return data
})
The difference here is that I also use isFetching
which determines whether the query is currently refecthing data or not. You’ll see why it matters in a moment. For now, let’s learn how you can modify remote data.
此处的区别在于,我还使用isFetching
来确定查询当前是否正在重新整理数据。 稍后您将了解其重要性。 现在,让我们学习如何修改远程数据。
useMutation挂钩 (The useMutation hook)
The useMutation
hook is commonly used to create/update/delete remote data. This function takes an asynchronous function to update your data (commonly between POST
, PUT
OR DELETE
request) and returns a mutate function that you can call to trigger the mutation.
useMutation
挂钩通常用于创建/更新/删除远程数据。 此函数采用异步函数来更新数据(通常在POST
, PUT
或DELETE
请求之间),并返回一个可以调用以触发突变的mutate函数。
const [mutate] = useMutation(
text => axios.post('/api/data', { text }),
)mutate("Learn about React Query")
You can also put optional functions that will be triggered only when the mutate function returns certain results, such as onSuccess
and onError
. In the sample repo, you can see that I used the mutate function to post new data into the API when the form is submitted. I also put the text input back to empty when the post request is successful:
您还可以放置仅在mutate函数返回某些结果(例如onSuccess
和onError
时才触发的可选函数。 在示例存储库中,您可以看到提交表单时,我使用了mutate函数将新数据发布到API中 。 发布请求成功后,我还将文本输入重新设置为空:
const [mutatePostTodo] = useMutation(
text => axios.post('/api/data', { text }),
{
onSuccess: () => {
// Query Invalidations
// queryCache.invalidateQueries('todos')
setText('')
},
}
)
But if you try to insert a new text into the demo app, you’ll see that the todo list is not refreshed. In order to tell React Query to refetch the todo list, you need to uncomment the code above setText
function:
但是,如果您尝试在演示应用程序中插入新文本,则会看到待办事项列表未刷新。 为了告诉React Query重新获取待办事项列表,您需要取消注释setText
函数上方的代码:
{
onSuccess: () => {
// Query Invalidations
queryCache.invalidateQueries('todos')
setText('')
},
}
The queryCache.invalidateQueries
will invalidate the cache with todo
key and make React Query fetch the data again.
queryCache.invalidateQueries
将使用todo
键使缓存无效,并使React Query再次获取数据。
queryCache实用程序 (The queryCache utility)
As you’ve seen in the demo DevTools, React Query will cache the retrieved data under the key todo
above, but it will automatically become stale after being fetched unless you configure the staleTime
.
正如你在演示DevTools可见,阵营查询将缓存中检索数据的项下todo
以上,但被提取,除非你配置后,它会自动变得陈旧staleTime
。
queryCache
is a utility instance that contains many functions that you can use to further manipulate queries. In the sample, you’ve seen how queryCache.invalidateQueries
function is used to make React Query send a new request to fetch the todo list. Here is the full list of available methods in queryCache.
queryCache
是一个实用程序实例,其中包含许多可用于进一步处理查询的功能。 在示例中,您已经看到如何使用queryCache.invalidateQueries
函数使React Query发送新请求以获取待办事项列表。 这是queryCache中可用方法的完整列表 。
结论 (Conclusion)
React Query is a great hook library for managing data requests that completely removes the need to put your remote data inside the global state. You just need to tell the library where you need to fetch your data, and it will handle caching, background updates, and stale data without any extra code or configuration.
React Query是一个很棒的钩子库,用于管理数据请求,完全消除了将远程数据放入全局状态的需求。 您只需要告诉库您需要在哪里获取数据,它就可以处理缓存,后台更新和陈旧的数据,而无需任何额外的代码或配置。
React Query also removes the need for useState
and useEffect
hooks and replace them with a few lines of React Query logic. In the long run, it will definitely help you keep your application maintainable, responsive, and fast.
React Query还消除了对useState
和useEffect
挂钩的需要,并用几行React Query逻辑替换了它们。 从长远来看,它绝对可以帮助您保持应用程序的可维护性,响应性和快速性。
If you’re interested to learn more, don’t forget to check out the React Query documentation.
如果您想了解更多信息,请不要忘记查看React Query文档 。
学到更多 (Learn More)
翻译自: https://blog.bitsrc.io/how-to-start-using-react-query-4869e3d5680d
react 查询节流