react-项目axios优化和懒加载优化

loading 2023年01月16日 113次浏览

1. axios全局默认配置和拦截器

项目里太多重复代码了,比如某个action:

//删除商品
export const deleteProduct = (id) => async (dispatch, getState) => {
	try {
		dispatch({ type: PRODUCT_DELETE_REQUEST })

		const { userLogin: { userInfo } } = getState();

		const config = {
			headers: {
				Authorization: `Bearer ${userInfo.token}`
			}
		}

		await axios.delete(`/api/products/${id}`, config)

		dispatch({ type: PRODUCT_DELETE_SUCCESS })
		alert('商品已被删除!')
	} catch (error) {
		dispatch({
			type: PRODUCT_DELETE_FAIL,
			payload: error.response && error.response.data.message ? error.response.data.message : error.message
		})
	}
}

//创建商品
export const createProduct = () => async (dispatch, getState) => {
	try {
		dispatch({ type: PRODUCT_CREATE_REQUEST })

		const { userLogin: { userInfo } } = getState()

		const config = {
			headers: {
				Authorization: `Bearer ${userInfo.token}`,
			}
		}

		const { data } = await axios.post(`/api/products`, {}, config)

		dispatch({ type: PRODUCT_CREATE_SUCCESS, payload: data })
	} catch (error) {
		dispatch({
			type: PRODUCT_CREATE_FAIL,
			payload:
				error.response && error.response.data.message
					? error.response.data.message
					: error.message,
		});
	}
}

像配置config来传token还有下面的error代码等,都是重复的,因此考虑进行优化。

frontend目录中创建一个utils文件夹,并在里面创建一个setupAxios.js文件

然后在index.js中引入

import store from './store';
import setupAxios from './utils/setupAxios';

setupAxios(store);

然后我们来看setupAxios这个文件,具体含义看注释:

toast只是一个捕获并显示错误的弹窗,不展开描述。

import axios from "axios";
import toast from "./toast";

function setupAxios(store) {
    // ?.表示如果有token 则取出
    const token = store.getState().userLogin.userInfo?.token;

    // axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;

    // 拦截请求
    axios.interceptors.request.use(function (config) {
        // 存在token则默认配置到请求头中
        if (token) {
            config.headers['Authorization'] = 'Bearer ' + token
        }
        return config;
    }, function (error) {
        return Promise.reject(error);
    });

    //拦截回应 将action中的错误处理抽离到这里
    axios.interceptors.response.use(function (response) {
        return response;
    }, function (error) {
        const message = error.response && error.response.data.message
            ? error.response.data.message
            : error.message

        if (message) {
            toast.error(message);
        }
        return Promise.reject(message);
    });

    // 默认配置config
    axios.defaults.headers.post['Content-Type'] = 'application/json';
    axios.defaults.headers.put['Content-Type'] = 'application/json';
    axios.defaults.headers.patch['Content-Type'] = 'application/json';
}

export default setupAxios;

配置完这个文件后我们回到action,修改一下刚刚的createProduct试试,可以对比上面的createProduct看:

//创建商品
export const createProduct = () => async (dispatch) => {
	try {
		dispatch({ type: PRODUCT_CREATE_REQUEST })

		const { data } = await axios.post(`/api/products`, {})

		dispatch({ type: PRODUCT_CREATE_SUCCESS, payload: data })
	} catch (error) {
		dispatch({
			type: PRODUCT_CREATE_FAIL,
			payload: error
		});
	}
}

可以看出来首先不用通过getState()从state中解构出userInfo来在config头信息中传递token了,其次也可以使得底下的错误处理代码中的payload十分简洁,实现了代码的优化。

2. 路由懒加载

运用到的技术是是另一篇博客中提到的React.lazy(),来看看是怎么具体应用到项目中的:

首先自己封装好一个LazyLoad方法,根据传入的路径包装组件:

const LazyLoad = (path) => {
  const Comp = React.lazy(() => import(`./screens/${path}`))
  return (
    <React.Suspense fallback={<>加载中...</>}>
      {<Comp />}
    </React.Suspense>
  )
}

然后在路由配置中进行修改:

这个项目用的还是React-Router5,因此注意这里要通过render的方式表示组件。

          <Route path="/login" render = {() =>{
            return LazyLoad('LoginScreen')
          }} />

这样就实现了这个组件的懒加载,至于要用到的参数通过useLocation,useHistory等等Hooks解决即可: