UseRequst Document: hooks.umijs.org/zh-CN/async
Umi Hooks Github address: github.com/umijs/hooks
UseRequest is a super powerful, fully produced network request Hooks that are now the ant mid-platform best practice built-in network request solution. UseRequest is recommended for ant internal applications and network requests.
UseRequest is probably the most powerful and accessible request class in the community right now. It can cover 99% of network request scenarios, whether it is read or write, whether it is normal request or paging request, whether it is caching or anti-throttling, all can be supported. Only you can’t think of it, can’t do without it (brag 🐂~).
Why useRequest?
Implementing a robust network request is not an easy task in component development. As I mentioned in my last article Umi Hooks – Help to embrace React Hooks, implementing a network request requires consideration of loading, race handling, component offloading, and so on.
Of course, with the logic encapsulation capabilities of React Hooks, we can encapsulate logic related to network requests. UseAsync in Umi Hooks does just that. Network requests are implemented in one line of code.
However, just one useAsync is not enough for daily work. Umi Hooks have numerous Hooks related to network requests. Examples include usePagination for paging requests, useSearch for requests with built-in shock protection, useAPI with built-in Umi-Request, useLoadMore for loading more scenarios, and so on.
Currently available Hooks have several obvious disadvantages:
- The overhead cost is high, so you need to select different Hooks for different scenarios.
- Hooks API, inconsistent underlying capabilities for all network requests. For example, usePagination does not support manual triggering, polling, etc.
- UseAsync is not capable enough to meet requirements for many scenarios, such as parallel requests.
At the same time, with the birth of ZeIT/SWR, it gave us a lot of inspiration, the original network request can also play this way! SWR has a lot of useful and unexpected capabilities. Such as:
- Screen focus reinitiates the request.
- SWR ability.
I’m going to make SWR simple. SWR is short for stale-while-revalidate. The most important capability of SWR is: when we initiate a network request, we will return the previously cached data first, then initiate a new network request behind, and finally re-trigger the component rendering with the new request result. The SWR feature is very user friendly in specific scenarios.
Based on the above two points, after many internal discussions, we have decided to create a powerful network request that covers all scenarios. UseRequest is born! Not only does it include all of the current Umi Hooks capabilities related to network requests, it also borrows a lot of the best features of SWR.
Ability to introduce
Basic network request
import { useRequest } from '@umijs/hooks';
function getUsername() {
return Promise.resolve('jack');
}
export default() = > {const { data, error, loading } = useRequest(getUsername)
if (error) return <div>failed to load</div>
if (loading) return <div>loading...</div>
return <div>Username: {data}</div>
}
Copy the code
This is the simplest example of a network request. In this example useRequest receives a Promise function. When the component is initialized, getUsername execution will be triggered automatically and data, loading, error and other data will be automatically managed. We only need to write corresponding UI implementation according to the state.
The online demo
Manual request
For “write” requests, we usually need to trigger manually, such as adding users, editing information, deleting users, and so on. UseRequest only needs to set manual = true to prevent initialization. Execution starts only when run is triggered.
import { useRequest } from '@umijs/hooks';
export default() = > {const { run, loading } = useRequest(changeUsername, {manual: true})
return (
<Button onClick={()= > run('new name')} loading={loading}>
Edit
</Button>)}Copy the code
The online demo
polling
For data that needs to be kept fresh, we often need to make continuous network requests to update the data. UseRequest can automatically initiate network requests as long as poilingInterval is configured.
import { useRequest } from '@umijs/hooks';
export default() = > {const { data } = useRequest(getUsername, { pollingInterval: 1000 })
return <div>Username: {data}</div>
}
Copy the code
Also, by setting pollingWhenHidden, we can intelligently suspend polling when the screen is hidden. When the screen is visible again, continue the request to save resources.
You can also manually turn the timer on and off with run/ Cancel.
The online demo
Parallel requests
What is a parallel request? You can see from the following figure that we need to maintain multiple request states for the same interface.
The parallel request in the example has several characteristics:
- If n users are deleted, n request states need to be maintained.
- If the same user is deleted multiple times, only the last request needs to be maintained.
UseRequest classifies requests by setting the fetchKey. For requests of the same classification, only one copy of status is maintained. Multiple states are maintained for different categories of requests. In the following code, we classify requests by userId, and we can fetches[userId] to get the status of the request for the current category!
export default() = > {const { run, fetches } = useRequest(deleteUser, {
manual: true.fetchKey: id= > id, // Different ID, different classification
});
return (
<div>
<Button loading={fetches.A? .loading} onClick={()= >{run('A')}}> Delete 1</Button>
<Button loading={fetches.B? .loading} onClick={()= >{run('B')}}> Delete 2</Button>
<Button loading={fetches.C? .loading} onClick={()= >{run('C')}}> Delete 3</Button>
</div>
);
};
Copy the code
The online demo
Anti-shake & throttling
Usually in the typing and searching scenario, we use anti-shake to save unnecessary network requests. With useRequest, you can easily throttle network requests by configuring a debounceInterval.
In the following example, no matter how many times run is called, only one request is sent after the input stops.
import { useRequest } from '@umijs/hooks';
export default() = > {const { data, loading, run, cancel } = useRequest(getEmail, {
debounceInterval: 500.manual: true
});
return (
<div>
<Select onSearch={run} loading={loading}>
{data && data.map(i => <Option key={i} value={i}>{i}</Option>)}
</Select>
</div>
);
};
Copy the code
Throttling is the same as anti-vibration. You only need to configure throttleInterval to implement throttling.
The online demo
Cache & SWR & preload
In the SWR scenario, we will cache the interface data. The next time we request the interface, we will return the cached data first, and at the same time, we will make a new network request behind the scenes. After the new data is obtained, the rendering will be triggered again.
For some interfaces whose data does not change frequently, SWR can greatly improve user experience. For example, in the following image example, when we visit the article a second time, the cached data is returned without any wait time. At the same time, we can see that the “last Access Time” is updated after 2 seconds, which means that new request data is returned.
UseRequest can enter SWR mode by configuring the cacheKey, which is fairly simple.
const { data, loading } = useRequest(getArticle, {
cacheKey: 'articleKey'});Copy the code
Note that data on the same cacheyKey is shared globally. With this feature, we can implement “preload” functionality. For example, when the mouse hover over the title of an article, we send a request to read the details of the article, so that by the time the user actually clicks on the article, the data is already cached.
The online demo
Screen focus rerequested
By configuring refreshOnWindowFocus, we can reinitiate network requests when the screen is refocused or visible. What does this feature do? It ensures synchronization of data across multiple tabs. It can also solve the data freshness problem of re-opening the site after a long interval.
Here’s a diagram from SWR to illustrate.
The online demo
Integrated Request library
For ease of use, useRequest integrates umi-Request. If the first parameter is not a Promise, we will initiate the network request through umi-request.
Of course, if you want to use Axios, you can customize your own request method using requstMethod.
1 / / usage
const { data, error, loading } = useRequest('/api/userInfo');
2 / / usage
const { data, error, loading } = useRequest({
url: '/api/changeUsername'.method: 'post'});3 / / usage
const { data, error, loading } = useRequest((userId) = > `/api/userInfo/${userId}`);
4 / / usage
const { loading, run } = useRequest((username) = > ({
url: '/api/changeUsername'.method: 'post'.data: { username },
}));
Copy the code
The online demo
paging
Tables and forms are the most popular mid-platform applications. For a table, we have a lot of request logic to deal with, including but not limited to:
- Page, pageSize, total management
- Filter criteria changes, resets paging, and re-initiates network requests
UseRequest enables you to automatically process common Table logic by configuring Pagination = true, and supports antD tables with a simple line of code that performs complex logic like the one shown in the following image.
import {useRequest} from '@umijs/hooks';
export default() = > {const [gender, setGender] = useState('male');
const { tableProps } = useRequest((params) = >{
returngetTableData({... params, gender}) }, {paginated: true.refreshDeps: [gender]
});
const columns = [];
return (
<Table columns={columns} rowKey="email" {. tableProps} / >
);
};
Copy the code
The online demo
To load more
Loading more scenarios is also a common requirement in daily development. In the loading scenario, we generally need to deal with:
- Page offset, pageSize and other management
- First load, load more state management
- Pull-up auto loads more
- The second time the component loads, it wants to record the previous data and scroll to the previous position
UseRequest goes into loadMore mode by setting loadMore = true, along with other parameters, to handle all of the above logic for you.
const { data, loading, loadMore, loadingMore } = useRequest((d) = >getLoadMoreList(d? .nextId,3), {
loadMore: true.cacheKey: 'loadMoreDemoCacheId'.fetchKey: d= > `${d? .nextId}- `});Copy the code
The online demo
More and more
Of course, as I said before, useReqeust has only the functions that you can’t imagine. Ha ha ha ~
In addition to the above features, we have several other capabilities that can be found in documentation. Such as loadingDelay.
loadingDelay
By setting loadingDelay, you can delay the time when loading becomes true. In this way, you can effectively avoid the jitter caused by loading changes when a request is quickly responded to.
conclusion
While useRequest has a lot of features, it’s inevitable that it won’t support some of the features you want to use. But don’t worry, you can pretty much extend it based on useRequest. Our paging mode, and loading more modes, are implemented based on the underlying capability extensions. You can reference their code to implement your own unique capabilities.
With useRequest, you can solve 99% of your daily network requests. Ollie give! Ollie give!
recruitment
Finally hit a recruitment advertisement, ant Financial experience technology department recruitment front! P6 and above required! If you are interested, please send your resume to us
I will help you follow up the progress of the interview, looking forward to your participation ~