简体   繁体   中英

React Hooks - proper way of handling errors

What is best way of handling errors etc. in react hooks? Lets say I have some custom Ajax Hook like useAjax and it returns data, error and function which can trigger request. Now I have two ways of handling errors. In some function or via useEffect . Examples below:

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

OR

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

Which method is correct? The second one seems to be more efficient but it a little bit argues with hooks because we may do not use returned by hook error or data.

Basically you can handle error in different way. One of them can be from axios Interceptor as well and this can be your global error handling for any kind of API call. Along with local component based error handling you can add Global error handling as well. To do this you can take following as example:

// Axios instance

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

// Set access token using axios request interceptor

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);
    }
);

// Handle refresh token using axios response interceptor

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);
    }
);

You can add more error status based on your need. This will help you to catch all kind of Global Error. And if you don't want to show Global error rather if you want to show localised error then you can also pass disableBadReqGlobalError as params to ignore this error handling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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