Prerequisite: You are expected to have read the Official documentation of React – Hook a few times.

Now, I basically took somebody else’s code and ran it myself. It’s not hard to look at, but it’s worth learning. If you want to see the original taste please go here to refer to the address, after a careful look you will feel too beautiful.

The following code encapsulates a custom hook similar to useHttp.

UseState Basic usage method

import React, { useState } from 'react';
function App() {
  const [data, setData] = useState({ hits: [] });
  return (
    <ul>
      {data.hits.map(item => (
        <li key={item.objectID}>
          <a href={item.url}>{item.title}</a>
        </li>
      ))}
    </ul>
  );
}
export default App;

Copy the code

Initializes the asynchronous AXIOS request

The most basic use of Axios

import React, { useState, useEffect } from 'react';
import axios from 'axios'; function App() { const [data, setData] = useState({ hits: [] }); useEffect(async () => { const result = await axios( 'http://hn.algolia.com/api/v1/search?query=redux', a); setData(result.data); }); return ( 
       ); } export default App;Copy the code

UseEffect is re-executed as soon as the component renders once and circulates requests

Can replace the react life cycle componentDidMount.

useEffect(async () => {
  const result = await axios(
    'http://hn.algolia.com/api/v1/search?query=redux',);setData(result.data); } []); // Passing an empty array each time will render only the first time the component is initializedCopy the code

UseEffect does not support async asynchronous functions

After the modification

useEffect(() => {
  const fetchData = async () => {
    const result = await axios(
      'http://hn.algolia.com/api/v1/search?query=redux',);setData(result.data); }; fetchData(); } []);Copy the code


The hook function has replaced componentDidMount, the lifecycle function hook


How to trigger the hook function

We use the input to trigger the useEffect hook instead of the state change

Automatically send requests when a Query changes

import React, { Fragment, useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('redux');

  useEffect(() => {
    const fetchData = async () => {
      const result = await axios(
        'http://hn.algolia.com/api/v1/search?query=redux',);setData(result.data); }; fetchData(); } []);return (
    <Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)} /> <ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a>  </li> ))} </ul> </Fragment> ); }export default App;
Copy the code


UseEffect is now only initializedPerform a

useEffect(() => {
  const fetchData = async () => {
    const result = await axios(
      `http://hn.algolia.com/api/v1/search?query=${query}`);setData(result.data); }, [])Copy the code

The useEffect hook function is now automatically reexecuted when the state in the second argument to the useEffect function changes on the input text

useEffect(() => {
  const fetchData = async () => {
    const result = await axios(
      `http://hn.algolia.com/api/v1/search?query=${query}`);setData(result.data); },[query]) // Add the state needed to trigger the hookCopy the code

As long as the Query changes. This function is going to re-execute and now it’s implemented and it’s going to send a request every time you type a character

The next step is to add a button to retrieve the input character and trigger the useEffect when the button is clicked

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('story'); const [search, setSearch] = useState(''); useEffect(() => { const fetchData = async () => { const result = await axios( `http://hn.algolia.com/api/v1/search?query=${query}`, ); setData(result.data); }; fetchData(); }, [query]); return ( 
       
        setQuery(event.target.value)} /> 
        
        
       ); }Copy the code


A query change is triggered each time the input is input. Button sets query to search when clicked

useEffect(() => {
  const fetchData = async () => {
    const result = await axios(
      `http://hn.algolia.com/api/v1/search?query=${search}`);setData(result.data);
  };

  fetchData();
}, [search]);
Copy the code

UseEffect is now triggered only when search changes. If search is triggered, it can only be retrieved by clicking on the button

The URL is extracted separately here

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('redux');
  const [url, setUrl] = useState(
    'http://hn.algolia.com/api/v1/search?query=redux',); useEffect(() => { const fetchData = async () => { const result = await axios(url);setData(result.data);
    };

    fetchData();
  }, [url]);

  return (
    <Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button
        type="button"
        onClick={() =>
          setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`) } > Search </button> <ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li>  ))} </ul> </Fragment> ); }Copy the code


Add LoAdding to hook

Set loAdding and render it to the UI before requesting it

import React, { Fragment, useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('redux');
  const [url, setUrl] = useState(
    'http://hn.algolia.com/api/v1/search?query=redux',); const [isLoading,setIsLoading] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsLoading(true);

      const result = await axios(url);

      setData(result.data);
      setIsLoading(false);
    };

    fetchData();
  }, [url]);

  return (
    <Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button
        type="button"
        onClick={() =>
          setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`) } > Search </button> {isLoading ? ( <div>Loading ... </div> ) : ( <ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li> ))} </ul> )} </Fragment> ); }export default App;
Copy the code


HOOK to add a display component to catch errors

import React, { Fragment, useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const [data, setData] = useState({ hits: [] });
  const [query, setQuery] = useState('redux');
  const [url, setUrl] = useState(
    'http://hn.algolia.com/api/v1/search?query=redux',); const [isLoading,setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);

      try {
        const result = await axios(url);

        setData(result.data);
      } catch (error) {
        setIsError(true);
      }

      setIsLoading(false);
    };

    fetchData();
  }, [url]);

  return (
    <Fragment>
      <input
        type="text"
        value={query}
        onChange={event => setQuery(event.target.value)}
      />
      <button
        type="button"
        onClick={() =>
          setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`) } > Search </button> {isError && <div>Something went wrong ... </div>} {isLoading ? ( <div>Loading ... </div> ) : ( <ul> {data.hits.map(item => ( <li key={item.objectID}> <a href={item.url}>{item.title}</a> </li> ))} </ul> )} </Fragment> ); }export default App;
Copy the code


Submit the form using the Form form

<Fragment>
  <form
    onSubmit={() =>
      setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`)
    }
  >
    <input
      type="text"
      value={query}
      onChange={event => setQuery(event.target.value)}
    />
    <button type="submit">Search</button> </form> {isError && <div>Something went wrong ... < / div >}... </Fragment>Copy the code

We need toTo prevent the defaultForm submission action

<form onSubmit={event => {
  setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`); event.preventDefault(); }} >Copy the code

A custom HOOK extracts the action of a HOOK for a separate wrapper call

const useHackerNewsApi = () => {
  const [data, setData] = useState({ hits: [] });
  const [url, setUrl] = useState(
    'http://hn.algolia.com/api/v1/search?query=redux',); const [isLoading,setIsLoading] = useState(false);
  const [isError, setIsError] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);

      try {
        const result = await axios(url);

        setData(result.data);
      } catch (error) {
        setIsError(true);
      }

      setIsLoading(false);
    };

    fetchData();
  }, [url]);

  return [{ data, isLoading, isError }, setUrl];
}
Copy the code

Using useHackerNewsApi

function App() {
  const [query, setQuery] = useState('redux');
  const [{ data, isLoading, isError }, doFetch] = useHackerNewsApi();

  return (
    <Fragment>
      <form onSubmit={event => {
        doFetch(`http://hn.algolia.com/api/v1/search?query=${query}`);

        event.preventDefault();
      }}>
        <input
          type="text"
          value={query}
          onChange={event => setQuery(event.target.value)}
        />
        <button type="submit">Search</button>
      </form>

      ...
    </Fragment>
  );
}

Copy the code


The URL that has not initialized the request at this time initializes the request parameters by passing the parameters

function App() {
  const [query, setQuery] = useState('redux');
  const [{ data, isLoading, isError }, doFetch] = useDataApi(
    'http://hn.algolia.com/api/v1/search?query=redux', { hits: [] }, ); . const useDataApi = (initialUrl, initialData) => { const [data,setData] = useState(initialData);
  const [url, setUrl] = useState(initialUrl); .Copy the code


The Reducer Hook was used to extract data

UseEffect sets the state of state several times, which is not easy to adjust. Reduce is used to centrally manage the status of the entire data

Import React, {Fragment, useState, useEffect, useReducer, // introduce usrReducer} from'react';
import axios from 'axios'; Const dataFetchReducer = (state, action) => {// Define the useReducer function... }; const useDataApi = (initialUrl, initialData) => { const [url,setUrl] = useState(initialUrl); Const [state, dispatch] = useReducer(dataFetchReducer, {// Use useReducer isLoading:false,
    isError: false, data: initialData, }); . };Copy the code

UseEffect in APP components

useEffect(() => {
  const fetchData = async () => {
    dispatch({ type: 'FETCH_INIT'}); // Use dispatch to set state try {const result = await axios(url); dispatch({type: 'FETCH_SUCCESS', payload: result.data });
    } catch (error) {
      dispatch({ type: 'FETCH_FAILURE'}); }}; fetchData(); }, [url]);Copy the code

After encapsulation using the useDataApi

const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl);

  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false, data: initialData, }); .return [state, setUrl];
};
Copy the code

DataFetchReducer Sets the returned state

const dataFetchReducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_INIT':
      return {
        ...state,
        isLoading: true,
        isError: false
      };
    case 'FETCH_SUCCESS':
      return {
        ...state,
        isLoading: false,
        isError: false,
        data: action.payload,
      };
    case 'FETCH_FAILURE':
      return {
        ...state,
        isLoading: false,
        isError: true}; default: throw new Error(); }};Copy the code

Setup didCance to prevent uninstalled components from setting state when multiple components share a custom hook


const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl);

  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false,
    data: initialData,
  });

  useEffect(() => {
    let didCancel = false;

    const fetchData = async () => {
      dispatch({ type: 'FETCH_INIT' });

      try {
        const result = await axios(url);

        if(! didCancel) { dispatch({type: 'FETCH_SUCCESS', payload: result.data });
        }
      } catch (error) {
        if(! didCancel) { dispatch({type: 'FETCH_FAILURE'}); }}}; fetchData();return () => {
      didCancel = true;
    };
  }, [url]);

  return [state, setUrl];
};

Copy the code

Reference address this is last August that notes today summarized to the nuggets, their own return to look at the basic knowledge of HOOK plug-in address here HOOK – API are big package source code open to see carefully I found why people can annual income tens of millions, we are so low.

Finally, say a word to yourself: learning channels and learning methods are important. If there are any good learning channels and ways to ask you to comment below recommended to me, we learn from each other a wave.