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.