N th Way of Front End Request - Play React Hook

Keywords: Javascript React JQuery axios mockjs

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.

Posted by dennismcdougall on Sun, 07 Jun 2020 18:21:00 -0700