I Love ReactJS

Encapsulation of axios and Management of API Interface in React Project

Preface

in the react project, we usually use the axios library, which is a promise-based http library, to interact with the background to obtain data. It can be run on the browser side and in node.js. It has many excellent features, such as intercepting requests and responses, canceling requests, converting json, client defense XSRF, and so on.

install

/ / install using npm
Npm install axios
/ / install using yarn
Yarn add axios
Undefined

introduce

in the project root, create a new request folder, and then create a new index.js and an api.js file in it. The index.js file is used to encapsulate our axios,api.js to uniformly manage our interface.

/ / introduce axios into index.js
import axios from 'axios';
/ / introduce qs module to serialize data of type post
import QS from 'qs';
/ / message prompt component of antd, which can be changed according to your own ui component.
import { message } from 'antd'

switching of environment

our project environment may have a development environment, a test environment and a production environment. We match our default interface url prefix through the environment variable of node. Here you need the global variable process of node, and process.env.NODE_ENV to distinguish between a development environment and a production environment.

/ / Save environment variables
const isPrd = process.env.NODE_ENV == 'production';

/ / distinguish the basic URL of development environment or production environment
export const basciUrl = isPrd ? 'https://www.production.com' : 'http://www.development.com'

the basic URL is exported here to prevent resources from being used differently in other places, and it is necessary to distinguish between production environment and development environment, and import can be used directly.

request interception

We can intercept a request before sending it. Why intercept it? what do we use to intercept the request? For example, some requests require users to log in before they can be accessed, or when post requests, we need to serialize the data we submit. At this point, we can intercept the request before it is sent to do what we want.

/ / set the basic path of axios
const service = axios.create({
  baseURL: basicUrl
})
/ / request interceptor
service.interceptors.request.use(config => { 
  / / whether the token exists in the local storage before each request is sent. You can also use Redux to only demonstrate how to get the token locally.
  / / if it exists, add token to all header requested by http, so that the backend judges your login status according to token.
  / / even if token exists locally, it is possible that token is out of date, so the return status should be judged in the response interceptor.
  const token = window.localStorage.getItem('userToken') || window.sessionStorage.getItem('userToken');
  / / add token to each request
  config.data = Object.assign({}, config.data, {
    token: token,
  })
  / / set the request header
  config.headers = {
    'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
  }
  config.data = QS.stringify(config.data)
  return config
}, error => { 
    return error;
})

here we talk about token. Generally speaking, after logging in, the user's token is stored locally through localStorage or sessionStorage, and then each time the user enters the page (that is, in main.js ), the token is first read from the local storage. If the token exists, the user has logged in, and the token status in the Redux is updated. Then, every time the API is requested, the token will be carried in the requested header, and the backend staff can determine whether your login has expired according to the token you carry. If you do not carry it, you have not logged in.

response interception

/ / response interceptor
service.interceptors.response.use(response => {
  / / do different things according to different status codes returned
  / / be sure to negotiate a unified error status code with the background developer.
  if (response.code) {
    switch (response.code) {
      case 200:
        return response.data;
      case 401:
        / / handling method of not logging in
        break;
      case 403:
        / / token expiration handling method
        break;
      default:
        message.error(response.data.msg)
    }
  } else { 
    return response;
  }
})
/ / finally export the encapsulated axios
export default service

the response interceptor is easy to understand, that is, the data returned to us by the server, which we can do some processing before we get it. For example, the above idea: if the status code returned by the background is 200, the data will be returned normally, otherwise we will make some errors according to the wrong status code type. the specific returned status code needs to be handled and negotiated with the background developer.
above message.error () method I introduced the library prompt component of antd. You need to use the prompt component according to your UI library

Unified Management of api

A neat api is like a circuit board. No matter how complex it is, it can make the whole circuit clear. As mentioned above, we will create a new api.js and store all our api interfaces in this file.

first we introduce our encapsulated axios into api.js

/ / Import our encapsulated axios
import service from './index'

now, for example, we have an interface that is a post request:

http://www.development.com/api/v1/articleEdit

We can encapsulate it like this in api.js:

export const apiArticleEdit = info => service.post('/api/v1/articleEdit', info);

We define a apiArticleEdit method that has a parameter info,info that we carry when we request the interface. Then we call our encapsulated axios method, the first parameter is our interface address, and the second parameter is the info parameter of apiArticleEdit , that is, the parameter object that is carried when the interface is requested. Finally, export apiArticleEdit through export.

then we can call our api interface in our page like this:

import React, { Component } from 'react'
 import { apiArticleEdit } from './request/api'
export default class App extends Component {
  componentDidMount() { 
    / / call the api interface and provide two parameters
    let params = { type: 2, author: 'Beigu Qingcha' }
    apiArticleEdit(params).then(res => { 
      / / other operations after data acquisition is successful
      //.....
      console.log(res)
    })
  }
  render() {
    return (
      <div>
        
      </div>
    )
  }
}

other api interfaces, just continue to expand below in api.js. Friendly tips, write notes for each interface!

one of the advantages of api interface management is that we centralize the api. If we need to modify the interface later, we can just find the corresponding modification in api.js, instead of going to every page to find our interface and then modify it will be very troublesome. The point is, in case the amount of modification is relatively large. In addition, if we modify the interface directly in our business code, it is easy to touch our business code and cause unnecessary trouble.

all right, finally, present the completed axios encapsulation code.

/ / introduce axios into index.js
import axios from 'axios';
/ / introduce qs module to serialize data of type post
import QS from 'qs';
/ / message prompt component of antd, which can be changed according to your own ui component.
import { message } from 'antd'

/ / Save environment variables
const isPrd = process.env.NODE_ENV == 'production';

/ / distinguish the basic URL of development environment or production environment
export const basciUrl = isPrd ? 'https://www.production.com' : 'http://www.development.com'

/ / set the basic path of axios
const service = axios.create({
  baseURL: basicUrl
})

/ / request interceptor
service.interceptors.request.use(config => { 
  / / whether the token exists in the local storage before each request is sent. You can also use Redux to only demonstrate how to get the token locally.
  / / if it exists, add token to all header requested by http, so that the backend judges your login status according to token.
  / / even if token exists locally, it is possible that token is out of date, so the return status should be judged in the response interceptor.
  const token = window.localStorage.getItem('userToken') || window.sessionStorage.getItem('userToken');
  / / add token to each request
  config.data = Object.assign({}, config.data, {
    token: token,
  })
  / / set the request header
  config.headers = {
    'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
  }
  / / serialize the request parameters, otherwise the post request parameters are not received properly in the background
  config.data = QS.stringify(config.data)
  return config
}, error => { 
    return error;
})

/ / response interceptor
service.interceptors.response.use(response => {
  / / do different things according to different status codes returned
  / / be sure to negotiate a unified error status code with the background developer.
  if (response.code) {
    switch (response.code) {
      case 200:
        return response.data;
      case 401:
        / / handling method of not logging in
        break;
      case 403:
        / / token expiration handling method
        break;
      default:
        message.error(response.data.msg)
    }
  } else { 
    return response;
  }
})
/ / finally export the encapsulated axios
export default service
Exit mobile version