Hooks handles Rest API requests

  • First, implement your own API Client
    • Regardless of the size of the project, first create your own API Client, and then send all requests through this Client
    • You can do some general configuration and processing for the server to be connected in the API Client, such as Token, URL, error handling, etc
// axios is a more convenient and semantic API than fetch

import axios from 'axios'

// Define related endpoint s

const endPoints = {

    test: "https://..../",

    prod: "https://.../"

}


// Create an instance of axios

const instance = axios.create({

    baseURL: endPoints.test,

    timeout: 3000,

    // Set a common header for all requests

    headers: { Authorization: "Bear mytoken" }

})

// All requests are preprocessed through the axios definition interceptor

instance.interceptors.response.use(

    (res) => {

        // Some logic of successful request

        return res

    },

    (err) => {

        if (err.response.status === 403) {

            // Uniformly handle unauthorized requests and jump to the login page

            document.location = '/login'

        }

        return Promise.reject(err)

    }

)

export default instance
  • Using Hooks to think about asynchronous requests

The essence of Hooks is that everything can be hooked, that is, we can turn any data source into a data source that can be bound in the React component.

For the API of get type, we can treat it as a remote resource. The only difference from local data is that it has three states:

  1. Data: refers to the data returned by the server after the request is successful;
  2. Error: if the request fails, the error information will be put into the error status;
  3. Pending: the request will be in pending status before returning.

Encapsulate the API for getting articles into a remote resource Hook

import { useState, useEffect } from 'react'

import apiClient from './apiClient'

const useArticle = (id) => {

    const [data,setDate] = useState(null)

    const [loading,setLoading] = useState(false)

    const [error,setError] = useState(null)

  
    useEffect(() => {

        setLoading(true)

        setError(null)

        setData(null)

        
        apiClient.get(`/getArticle/${id}`)

                .then((res) => {

                    setData(res.data)

                    setLoading(false)

                })

                .catch((err) => {

                    setError(err)

                    setLoading(false)

                })

    },[id])


    // Take the three states as the return value of Hook    

    // Three states of remote data

    reuturn {

        loading,

        error,

        data

    }
}

When you want to display an article, it is no longer a specific API call, but can be regarded as a remote data.

import useArticle from './useArticle'

const ArticleView = ({ id }) => {

    const { data, loading, error } = useArticle(id)

    if (error) return 'Failed'

    if (!data || loading) return 'Loading...'

    return (

        <div>

            // ...

        </div>

    )

}

In the project, each Get request can be made into such a Hook. The data request and processing logic are put into Hooks to realize the isolation of Model and View.

Why not provide a general Hook and pass in the API address?

In fact, it is OK, but it is written separately to ensure that each Hook is simple enough. Generally speaking, in order to make the returned data of the server meet the presentation requirements on the UI, it usually needs further processing.

  • Multiple API calls: how to handle concurrent or serial requests?

For example, as a complete page, you need to send three requests:

  1. Get article content
  2. Get author information, including name and avatar address
  3. Get a list of comments for an article

These three requests contain both concurrent and serial scenarios: article content and article comment list can be requested concurrently through the same article id. The author information needs to request the author information according to the article information after the article information is returned. It is a serial scene.

If it is realized with traditional ideas:

const [article, comments] = await Promise.all([

    fetchArticle(articleId),

    fetchComments(articleId)

])

const author = await fetchAuthor(article.userId)

Different from the above, the judgment of existence is added to useEffect

So, on the display page of the article

Added by Sikk Industries on Sat, 15 Jan 2022 04:33:05 +0200