I wrote an article a few years ago - " My Opinions on the Differences between Jquery ajax, Axios, Fetch "- Analyses the differences between ajax,axios and fetch in terms of principle and usage.Now, starting with a small ex amp le, this paper uses react hook to dissect a new way of requesting data; and through this custom HOOK, it introduces and introduces other React Hook libraries.Say nothing more. We'll start right away.
Story Origin
Recently I wrote a project in UMI and found that umi's network request actually says this:
import { useRequest } from '@umijs/hooks'; import Mock from 'mockjs'; import React from 'react'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock('@name')); }, 1000); }); } 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> }
PS: Want a go
In this example, we use useRequest to encapsulate the asynchronous request getUsername and end up with an object with three values:
data: data returned by normal requests
error: error message for exception request
loading: Is it in the load/request state
This eliminates the logic of setting the newly requested data to the state of the component and makes the entire code much clearer.Instead of using useRequest, our code should look like this:
import { useRequest } from "@umijs/hooks"; import Mock from "mockjs"; import React from "react"; const { useState, useEffect } = React; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } export default () => { const [username, setUsername] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Do you want to wrap asynchronous requests? async function getUsernameAsync() { setLoading(true); const res = await getUsername(); // In this example, getUsername always returns the correct value for the request, assuming that when the request fails, it returns an error object if (typeof res === "string") { setUsername(res); } else { setError(res); } setLoading(false); } // Initiate Request useEffect(() => { getUsernameAsync(); }, []); if (error) { return <div>failed to load</div>; } if (loading) { return <div>loading...</div>; } return <div>Username: {username}</div>; };
Now it should be clear that useRequest has helped us smooth out the three state values so that we can use them directly.It's a little amazing, how does it work?Are there any other capabilities?Get to the next lie now!
Implementation Principle
In this section, we explain why @umijs/hooks useRequest could do that in the previous section by code analysis of react-use useAsync
The useAsync code is relatively simple, and the useRequest code incorporates many of its other features, which are essentially consistent in principle.
react-use: [Project Address ]A react hook function library, equivalent to JQuery for react hook, provides a variety of basic Hook encapsulation capabilities: sending requests, getting/setting cookie s, getting mouse positions, and so on.
The Chinese translation of PS:react-use is still for V8.1.3, while the current version is V15.1.1, so you can read the English documents directly.
First of all, stick a note about how to use it:
import {useAsync} from 'react-use'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } const Demo = () => { const state = useAsync(getUsername); return ( <div> {state.loading? <div>Loading...</div> : state.error? <div>Error...</div> : <div>Value: {state.value}</div> } </div> ); };
As you can see, the usage is the same, so let's see how they are implemented -- because useAsync references its own useAsyncFn, let's analyze useAsyncFn directly below.
/* eslint-disable */ // import is not concerned for the moment import { DependencyList, useCallback, useState, useRef } from 'react'; import useMountedState from './useMountedState'; import { FnReturningPromise, PromiseType } from './util'; // AsyncState has four states export type AsyncState<T> = | { loading: boolean; error?: undefined; value?: undefined; } | { loading: true; error?: Error | undefined; value?: T; } | { loading: false; error: Error; value?: undefined; } | { loading: false; error?: undefined; value: T; }; // Neither does the type of ts matter for the time being type StateFromFnReturningPromise<T extends FnReturningPromise> = AsyncState<PromiseType<ReturnType<T>>>; export type AsyncFnReturn<T extends FnReturningPromise = FnReturningPromise> = [StateFromFnReturningPromise<T>, T]; // Body, accepts three parameters, an asynchronous request function, an array type dependency, an initial state, and the default is load=false export default function useAsyncFn<T extends FnReturningPromise>( fn: T, deps: DependencyList = [], initialState: StateFromFnReturningPromise<T> = { loading: false } ): AsyncFnReturn<T> { // Record is the first call const lastCallId = useRef(0); // Determine if the current component is mounted complete const isMounted = useMountedState(); // Set state const [state, set] = useState<StateFromFnReturningPromise<T>>(initialState); // useCallback is designed for performance optimization and guarantees that the same callback function is returned, so we can just look directly at the callback function inside it const callback = useCallback((...args: Parameters<T>): ReturnType<T> => { // The number of calls const callId = ++lastCallId.current; // Set directly to loading to true set(prevState => ({ ...prevState, loading: true })); // Set state when asynchronous request ends return fn(...args).then( value => { // When the user requests more than once, only the value of the last request is returned isMounted() && callId === lastCallId.current && set({ value, loading: false }); return value; }, error => { isMounted() && callId === lastCallId.current && set({ error, loading: false }); return error; } ) as ReturnType<T>; }, deps); // Returns two values, state and encapsulated callback return [state, (callback as unknown) as T]; }
This is the implementation logic of useAsyncFn, and you can see that it essentially works the same way as the mad state set in our first section, but this opens a new door to encapsulating requests. What are the capabilities?
Introduction to SWR and useRequest
Undoubtedly, the encapsulation of asynchronous requests in Sections 1 and 2 avoids our repeated processing of different requests and is highly effective.Is there anything more compelling about that?Here they come!
SWR: [Project Address] An asynchronous request library for a React hook.Provides capabilities for asynchronous requests, such as SWR (stale-while-revalidate, returning previously requested cached data before re-requesting and refreshing), paging, screen focus sending requests, and so on.useRequest is also a reference for SWR.
I wrote an article a few years ago - " My Opinions on the Differences between Jquery ajax, Axios, Fetch "- Analyses the differences between ajax,axios and fetch in terms of principle and usage.Now, starting with a small ex amp le, this paper uses react hook to dissect a new way of requesting data; and through this custom HOOK, it introduces and introduces other React Hook libraries.Say nothing more. We'll start right away.
Story Origin
Recently I wrote a project in UMI and found that umi's network request actually says this:
import { useRequest } from '@umijs/hooks'; import Mock from 'mockjs'; import React from 'react'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock('@name')); }, 1000); }); } 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> }
PS: Want a go
In this example, we use useRequest to encapsulate the asynchronous request getUsername and end up with an object with three values:
data: data returned by normal requests
error: error message for exception request
loading: Is it in the load/request state
This eliminates the logic of setting the newly requested data to the state of the component and makes the entire code much clearer.Instead of using useRequest, our code should look like this:
import { useRequest } from "@umijs/hooks"; import Mock from "mockjs"; import React from "react"; const { useState, useEffect } = React; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } export default () => { const [username, setUsername] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Do you want to wrap asynchronous requests? async function getUsernameAsync() { setLoading(true); const res = await getUsername(); // In this example, getUsername always returns the correct value for the request, assuming that when the request fails, it returns an error object if (typeof res === "string") { setUsername(res); } else { setError(res); } setLoading(false); } // Initiate Request useEffect(() => { getUsernameAsync(); }, []); if (error) { return <div>failed to load</div>; } if (loading) { return <div>loading...</div>; } return <div>Username: {username}</div>; };
Now it should be clear that useRequest has helped us smooth out the three state values so that we can use them directly.It's a little amazing, how does it work?Are there any other capabilities?Get to the next lie now!
Implementation Principle
In this section, we explain why @umijs/hooks useRequest could do that in the previous section by code analysis of react-use useAsync
The useAsync code is relatively simple, and the useRequest code incorporates many of its other features, which are essentially consistent in principle.
react-use: [Project Address ]A react hook function library, equivalent to JQuery for react hook, provides a variety of basic Hook encapsulation capabilities: sending requests, getting/setting cookie s, getting mouse positions, and so on.
The Chinese translation of PS:react-use is still for V8.1.3, while the current version is V15.1.1, so you can read the English documents directly.
First of all, stick a note about how to use it:
import {useAsync} from 'react-use'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } const Demo = () => { const state = useAsync(getUsername); return ( <div> {state.loading? <div>Loading...</div> : state.error? <div>Error...</div> : <div>Value: {state.value}</div> } </div> ); };
As you can see, the usage is the same, so let's see how they are implemented -- because useAsync references its own useAsyncFn, let's analyze useAsyncFn directly below.
/* eslint-disable */ // import is not concerned for the moment import { DependencyList, useCallback, useState, useRef } from 'react'; import useMountedState from './useMountedState'; import { FnReturningPromise, PromiseType } from './util'; // AsyncState has four states export type AsyncState<T> = | { loading: boolean; error?: undefined; value?: undefined; } | { loading: true; error?: Error | undefined; value?: T; } | { loading: false; error: Error; value?: undefined; } | { loading: false; error?: undefined; value: T; }; // Neither does the type of ts matter for the time being type StateFromFnReturningPromise<T extends FnReturningPromise> = AsyncState<PromiseType<ReturnType<T>>>; export type AsyncFnReturn<T extends FnReturningPromise = FnReturningPromise> = [StateFromFnReturningPromise<T>, T]; // Body, accepts three parameters, an asynchronous request function, an array type dependency, an initial state, and the default is load=false export default function useAsyncFn<T extends FnReturningPromise>( fn: T, deps: DependencyList = [], initialState: StateFromFnReturningPromise<T> = { loading: false } ): AsyncFnReturn<T> { // Record is the first call const lastCallId = useRef(0); // Determine if the current component is mounted complete const isMounted = useMountedState(); // Set state const [state, set] = useState<StateFromFnReturningPromise<T>>(initialState); // useCallback is designed for performance optimization and guarantees that the same callback function is returned, so we can just look directly at the callback function inside it const callback = useCallback((...args: Parameters<T>): ReturnType<T> => { // The number of calls const callId = ++lastCallId.current; // Set directly to loading to true set(prevState => ({ ...prevState, loading: true })); // Set state when asynchronous request ends return fn(...args).then( value => { // When the user requests more than once, only the value of the last request is returned isMounted() && callId === lastCallId.current && set({ value, loading: false }); return value; }, error => { isMounted() && callId === lastCallId.current && set({ error, loading: false }); return error; } ) as ReturnType<T>; }, deps); // Returns two values, state and encapsulated callback return [state, (callback as unknown) as T]; }
This is the implementation logic of useAsyncFn, and you can see that it essentially works the same way as the mad state set in our first section, but this opens a new door to encapsulating requests. What are the capabilities?
Introduction to SWR and useRequest
Undoubtedly, the encapsulation of asynchronous requests in Sections 1 and 2 avoids our repeated processing of different requests and is highly effective.Is there anything more compelling about that?Here they come!
SWR: [Project Address] An asynchronous request library for a React hook.Provides capabilities for asynchronous requests, such as SWR (stale-while-revalidate, returning previously requested cached data before re-requesting and refreshing), paging, screen focus sending requests, and so on.useRequest is also a reference for SWR.
I wrote an article a few years ago - " My Opinions on the Differences between Jquery ajax, Axios, Fetch "- Analyses the differences between ajax,axios and fetch in terms of principle and usage.Now, starting with a small ex amp le, this paper uses react hook to dissect a new way of requesting data; and through this custom HOOK, it introduces and introduces other React Hook libraries.Say nothing more. We'll start right away.
Story Origin
Recently I wrote a project in UMI and found that umi's network request actually says this:
import { useRequest } from '@umijs/hooks'; import Mock from 'mockjs'; import React from 'react'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock('@name')); }, 1000); }); } 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> }
PS: Want a go
In this example, we use useRequest to encapsulate the asynchronous request getUsername and end up with an object with three values:
data: data returned by normal requests
error: error message for exception request
loading: Is it in the load/request state
This eliminates the logic of setting the newly requested data to the state of the component and makes the entire code much clearer.Instead of using useRequest, our code should look like this:
import { useRequest } from "@umijs/hooks"; import Mock from "mockjs"; import React from "react"; const { useState, useEffect } = React; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } export default () => { const [username, setUsername] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Do you want to wrap asynchronous requests? async function getUsernameAsync() { setLoading(true); const res = await getUsername(); // In this example, getUsername always returns the correct value for the request, assuming that when the request fails, it returns an error object if (typeof res === "string") { setUsername(res); } else { setError(res); } setLoading(false); } // Initiate Request useEffect(() => { getUsernameAsync(); }, []); if (error) { return <div>failed to load</div>; } if (loading) { return <div>loading...</div>; } return <div>Username: {username}</div>; };
Now it should be clear that useRequest has helped us smooth out the three state values so that we can use them directly.It's a little amazing, how does it work?Are there any other capabilities?Get to the next lie now!
Implementation Principle
In this section, we explain why @umijs/hooks useRequest could do that in the previous section by code analysis of react-use useAsync
The useAsync code is relatively simple, and the useRequest code incorporates many of its other features, which are essentially consistent in principle.
react-use: [Project Address ]A react hook function library, equivalent to JQuery for react hook, provides a variety of basic Hook encapsulation capabilities: sending requests, getting/setting cookie s, getting mouse positions, and so on.
The Chinese translation of PS:react-use is still for V8.1.3, while the current version is V15.1.1, so you can read the English documents directly.
First of all, stick a note about how to use it:
import {useAsync} from 'react-use'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } const Demo = () => { const state = useAsync(getUsername); return ( <div> {state.loading? <div>Loading...</div> : state.error? <div>Error...</div> : <div>Value: {state.value}</div> } </div> ); };
As you can see, the usage is the same, so let's see how they are implemented -- because useAsync references its own useAsyncFn, let's analyze useAsyncFn directly below.
/* eslint-disable */ // import is not concerned for the moment import { DependencyList, useCallback, useState, useRef } from 'react'; import useMountedState from './useMountedState'; import { FnReturningPromise, PromiseType } from './util'; // AsyncState has four states export type AsyncState<T> = | { loading: boolean; error?: undefined; value?: undefined; } | { loading: true; error?: Error | undefined; value?: T; } | { loading: false; error: Error; value?: undefined; } | { loading: false; error?: undefined; value: T; }; // Neither does the type of ts matter for the time being type StateFromFnReturningPromise<T extends FnReturningPromise> = AsyncState<PromiseType<ReturnType<T>>>; export type AsyncFnReturn<T extends FnReturningPromise = FnReturningPromise> = [StateFromFnReturningPromise<T>, T]; // Body, accepts three parameters, an asynchronous request function, an array type dependency, an initial state, and the default is load=false export default function useAsyncFn<T extends FnReturningPromise>( fn: T, deps: DependencyList = [], initialState: StateFromFnReturningPromise<T> = { loading: false } ): AsyncFnReturn<T> { // Record is the first call const lastCallId = useRef(0); // Determine if the current component is mounted complete const isMounted = useMountedState(); // Set state const [state, set] = useState<StateFromFnReturningPromise<T>>(initialState); // useCallback is designed for performance optimization and guarantees that the same callback function is returned, so we can just look directly at the callback function inside it const callback = useCallback((...args: Parameters<T>): ReturnType<T> => { // The number of calls const callId = ++lastCallId.current; // Set directly to loading to true set(prevState => ({ ...prevState, loading: true })); // Set state when asynchronous request ends return fn(...args).then( value => { // When the user requests more than once, only the value of the last request is returned isMounted() && callId === lastCallId.current && set({ value, loading: false }); return value; }, error => { isMounted() && callId === lastCallId.current && set({ error, loading: false }); return error; } ) as ReturnType<T>; }, deps); // Returns two values, state and encapsulated callback return [state, (callback as unknown) as T]; }
This is the implementation logic of useAsyncFn, and you can see that it essentially works the same way as the mad state set in our first section, but this opens a new door to encapsulating requests. What are the capabilities?
Introduction to SWR and useRequest
Undoubtedly, the encapsulation of asynchronous requests in Sections 1 and 2 avoids our repeated processing of different requests and is highly effective.Is there anything more compelling about that?Here they come!
SWR: [Project Address] An asynchronous request library for a React hook.Provides capabilities for asynchronous requests, such as SWR (stale-while-revalidate, returning previously requested cached data before re-requesting and refreshing), paging, screen focus sending requests, and so on.useRequest is also a reference for SWR.
I wrote an article a few years ago - " My Opinions on the Differences between Jquery ajax, Axios, Fetch "- Analyses the differences between ajax,axios and fetch in terms of principle and usage.Now, starting with a small ex amp le, this paper uses react hook to dissect a new way of requesting data; and through this custom HOOK, it introduces and introduces other React Hook libraries.Say nothing more. We'll start right away.
Story Origin
Recently I wrote a project in UMI and found that umi's network request actually says this:
import { useRequest } from '@umijs/hooks'; import Mock from 'mockjs'; import React from 'react'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock('@name')); }, 1000); }); } 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> }
PS: Want a go
In this example, we use useRequest to encapsulate the asynchronous request getUsername and end up with an object with three values:
data: data returned by normal requests
error: error message for exception request
loading: Is it in the load/request state
This eliminates the logic of setting the newly requested data to the state of the component and makes the entire code much clearer.Instead of using useRequest, our code should look like this:
import { useRequest } from "@umijs/hooks"; import Mock from "mockjs"; import React from "react"; const { useState, useEffect } = React; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } export default () => { const [username, setUsername] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Do you want to wrap asynchronous requests? async function getUsernameAsync() { setLoading(true); const res = await getUsername(); // In this example, getUsername always returns the correct value for the request, assuming that when the request fails, it returns an error object if (typeof res === "string") { setUsername(res); } else { setError(res); } setLoading(false); } // Initiate Request useEffect(() => { getUsernameAsync(); }, []); if (error) { return <div>failed to load</div>; } if (loading) { return <div>loading...</div>; } return <div>Username: {username}</div>; };
Now it should be clear that useRequest has helped us smooth out the three state values so that we can use them directly.It's a little amazing, how does it work?Are there any other capabilities?Get to the next lie now!
Implementation Principle
In this section, we explain why @umijs/hooks useRequest could do that in the previous section by code analysis of react-use useAsync
The useAsync code is relatively simple, and the useRequest code incorporates many of its other features, which are essentially consistent in principle.
react-use: [Project Address ]A react hook function library, equivalent to JQuery for react hook, provides a variety of basic Hook encapsulation capabilities: sending requests, getting/setting cookie s, getting mouse positions, and so on.
The Chinese translation of PS:react-use is still for V8.1.3, while the current version is V15.1.1, so you can read the English documents directly.
First of all, stick a note about how to use it:
import {useAsync} from 'react-use'; function getUsername(): Promise<string> { return new Promise(resolve => { setTimeout(() => { resolve(Mock.mock("@name")); }, 1000); }); } const Demo = () => { const state = useAsync(getUsername); return ( <div> {state.loading? <div>Loading...</div> : state.error? <div>Error...</div> : <div>Value: {state.value}</div> } </div> ); };
As you can see, the usage is the same, so let's see how they are implemented -- because useAsync references its own useAsyncFn, let's analyze useAsyncFn directly below.
/* eslint-disable */ // import is not concerned for the moment import { DependencyList, useCallback, useState, useRef } from 'react'; import useMountedState from './useMountedState'; import { FnReturningPromise, PromiseType } from './util'; // AsyncState has four states export type AsyncState<T> = | { loading: boolean; error?: undefined; value?: undefined; } | { loading: true; error?: Error | undefined; value?: T; } | { loading: false; error: Error; value?: undefined; } | { loading: false; error?: undefined; value: T; }; // Neither does the type of ts matter for the time being type StateFromFnReturningPromise<T extends FnReturningPromise> = AsyncState<PromiseType<ReturnType<T>>>; export type AsyncFnReturn<T extends FnReturningPromise = FnReturningPromise> = [StateFromFnReturningPromise<T>, T]; // Body, accepts three parameters, an asynchronous request function, an array type dependency, an initial state, and the default is load=false export default function useAsyncFn<T extends FnReturningPromise>( fn: T, deps: DependencyList = [], initialState: StateFromFnReturningPromise<T> = { loading: false } ): AsyncFnReturn<T> { // Record is the first call const lastCallId = useRef(0); // Determine if the current component is mounted complete const isMounted = useMountedState(); // Set state const [state, set] = useState<StateFromFnReturningPromise<T>>(initialState); // useCallback is designed for performance optimization and guarantees that the same callback function is returned, so we can just look directly at the callback function inside it const callback = useCallback((...args: Parameters<T>): ReturnType<T> => { // The number of calls const callId = ++lastCallId.current; // Set directly to loading to true set(prevState => ({ ...prevState, loading: true })); // Set state when asynchronous request ends return fn(...args).then( value => { // When the user requests more than once, only the value of the last request is returned isMounted() && callId === lastCallId.current && set({ value, loading: false }); return value; }, error => { isMounted() && callId === lastCallId.current && set({ error, loading: false }); return error; } ) as ReturnType<T>; }, deps); // Returns two values, state and encapsulated callback return [state, (callback as unknown) as T]; }
This is the implementation logic of useAsyncFn, and you can see that it essentially works the same way as the mad state set in our first section, but this opens a new door to encapsulating requests. What are the capabilities?
Introduction to SWR and useRequest
Undoubtedly, the encapsulation of asynchronous requests in Sections 1 and 2 avoids our repeated processing of different requests and is highly effective.Is there anything more compelling about that?Here they come!
SWR:[Project Address ] An asynchronous request library for a React hook.Provides capabilities for asynchronous requests, such as SWR (stale-while-revalidate, returning previously requested cached data before re-requesting and refreshing), paging, screen focus sending requests, and so on.useRequest is also a reference for SWR.
useRequest: [Project Address ]Ant Platform Standard Request Hook Warehouse.Provides a variety of capabilities and is built into umi.
Specific capabilities you can see the " useRequest-Ant Console Standard Request Hooks "Is already exhaustive, but I'll just tell you more about it.
summary
Starting with the use of case for a umi request, this paper analyses its principle.During this process, react-use, a common base hook warehouse, and SWR/useRequest, two asynchronous request hook warehouses are introduced.By using their capabilities, we can greatly improve our code writing efficiency.
If you haven't used a react hook yet, join the react hook family right away, because as it grows, it really has many features that class component doesn't have.