繁体   English   中英

React Hooks - 处理错误的正确方法

[英]React Hooks - proper way of handling errors

在反应钩子中处理错误等的最佳方法是什么? 假设我有一些像useAjax这样的自定义 Ajax Hook,它返回数据、错误和可以触发请求的函数。 现在我有两种处理错误的方法。 在某些函数中或通过useEffect 下面的例子:

    const {data, error, sendRequest} = useAjax()
    
    const handleSubmit = () => {
       sendRequest()
    }
    
    useEffect(() => {
       if (error) {
          // display some error/set state
       }
    }, [error])

或者

    const {data, error, sendRequest} = useAjax()
    
    const handleSubmit = async () => {
       try {
          await sendRequest()
       } catch {
          //display error
          // set some state
       }
    }

哪种方法是正确的? 第二个似乎更有效,但它与钩子有点争论,因为我们可能不使用由钩子错误或数据返回的。

基本上你可以用不同的方式处理错误。 其中之一也可以来自 axios Interceptor,这可以是您对任何类型的 API 调用的全局错误处理。 除了基于本地组件的错误处理,您还可以添加全局错误处理。 为此,您可以以以下为例:

// Axios 实例

const api = axios.create({
    baseURL,
});

// 使用 axios 请求拦截器设置访问令牌

api.interceptors.request.use(
    (config) => {
        showAppLoader();
        // Token from localStorage
        const token = store.get('access_token');

        if (token) {
            config.headers['Authorization'] = 'Bearer ' + token;
        }

        return config;
    },
    (error) => {
        hideAppLoader();
        Promise.reject(error);
    }
);

// 使用 axios 响应拦截器处理刷新令牌

api.interceptors.response.use(
    (response) => {
        hideAppLoader();
        return response;
    },
    (error) => {
        hideAppLoader();
        const originalRequest = error.config;

        // Prevent infinite loop when refresh token request is 401;
        if (
            error.response.status === 401 &&
            originalRequest.url === `${baseURL}${endpoints.TOKEN}`
        ) {
            return Promise.reject(error);
        }

        if (error.response.status === 401 && !originalRequest._retry) {
            originalRequest._retry = true;

            // Refresh token from localStorage
            const refreshToken = store.get('refresh_token');

            // Refresh token request body
            const data = new FormData();
            data.append('type', 'refresh_token');
            data.append('refresh_token', refreshToken);

            return axios
                .post(endpoints.TOKEN, data, {
                    auth: {
                        // eslint-disable-next-line no-undef
                        username: process.env['REACT_APP_CLIENT_ID'],
                        // eslint-disable-next-line no-undef
                        password: process.env['REACT_APP_CLIENT_SECRET'],
                    },
                })
                .then((res) => {
                    if (res.status === 200 && res.data) {
                        const new_access_token = res.data.access_token;
                        const new_refresh_token = res.data.refresh_token;

                        // Set new tokens to localStorage
                        store.set('access_token', new_access_token);
                        store.set('refresh_token', new_refresh_token);

                        api.defaults.headers.common['Authorization'] =
                            'Bearer ' + new_access_token;
                        return api(originalRequest);
                    }
                })
                .catch((err) => {
                    // Reset tokens to localStorage if refresh token failed
                    store.set('access_token', '');
                    store.set('refresh_token', '');
                });
        }

        // disableBadReqGlobalError = Disable Error Notification for bad request/400 error!
        const { disableBadReqGlobalError } = originalRequest;

        if (error.response.status === 500) {
            showServerErrorAlert();
        }

        if (error.response.status === 400 && !disableBadReqGlobalError) {
            notification(
                '400 - Bad Request',
                'Wrong information provided on the form! Please correct and try again!',
                'warning'
            );
        }

        if (error.response.status === 404) {
            notification(
                '404 - Not Found',
                'Something went wrong! Sorry for this inconvenience. Please contact with us.',
                'error'
            );
        }

        return Promise.reject(error);
    }
);

您可以根据需要添加更多错误状态。 这将帮助您捕获所有类型的全局错误。 如果您不想显示全局错误,而不想显示本地化错误,那么您还可以将disableBadReqGlobalError作为参数传递以忽略此错误处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM