Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to handle loading, success and error in redux

Problem Summary

I am working on a project where we use a lot of API Requests and we expect that to scale even further with many new endpoints. The project is built using Redux and Hooks. We would like to separate the API requests from the components that's why we are aiming to put everything in redux. However, a problem arises: there is a lot of boilerplate like: FETCH_DATA_REQUEST, FETCH_DATA_SUCCESS, FETCH_DATA_ERROR that need to be reproduced for each and every endpoint. Furthermore, we have to handle the loading, success and error for all of them. This seems to be a lot of code especially as the app grows.

What we tried

We tried to create a custom API Hook which uses useReducer behind the scenes and returns a dynamically generated loading, success and error variables. This hook exposes a sendRequest method that can be used in the components as such:

sendRequest("GET", `${BASE_URL}/api/endpoint`);

It works well but there is a problem, we are building the API endpoints in the component and that's what we would like to change. That's why we turned to redux.

Ideally we would like to separate the loading and error logic from the reducers and I'm wondering if anyone had an idea (or knows a package) that can help reducing the boilerplate and achieving this goal.

like image 713
Bassem Avatar asked May 05 '20 11:05

Bassem


People also ask

How do you handle loading in Redux?

Don't put UI logic into reducers instead put it into a separate reducer. When handling asynchronous actions in your application, most of the time you want to let users know that their request is being executed in form of some loading indicator.

How do you handle errors in Redux?

Usually the best approach to error handling with redux is to have an error field in state that is then passed to an error component. The error component doesn't have to just display an error, it could also do side effects with useEffect . How the error is set/unset depends on your application.

Which is better Usecontext or Redux?

If you're only using Redux to avoid passing down props, you can replace it with Context API. Context is great for sharing trivial pieces of state between components. Redux is much more powerful and provides a set of handy features that Context doesn't have.

How do you maintain the data in Redux on reloading the application?

If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware. Check out the redux-persist and redux-storage middleware. They both try to accomplish the same task of storing your redux state so that it may be saved and loaded at will.


2 Answers

const loading = () => {type: 'loading'}
const loaded = (data) => {type: 'loaded', data: data}
const error = (err) => {type: 'error', data: err}

const load = async() => {
dispatch(loading)
try{
 const res = await fetch ---- fetch here
if(res){dispatch(loaded(res))}
}catch{
(err) => {dispatch(error())}
} 
}

Reducer

const initialState = {
  loading: false,
  data: {},
 error: false
}

export default(state = initialState, {type, data}) => {
  switch(type){
   case 'loading':
    return {
     ...state,
     loading: true
    }

    case 'loaded':
    return {
     ...state,
     loading: false,
     data: data
    }

    case 'error':
    return {
     ...state,
     loading: false,
     error: data
    }
  }
}
like image 72
costal oktopus Avatar answered Sep 19 '22 19:09

costal oktopus


What you can find in the redux official doc is :

When you call an asynchronous API, there are two crucial moments in time: the moment you start the call, and the moment when you receive an answer (or a timeout).

Each of these two moments usually require a change in the application state; to do that, you need to dispatch normal actions that will be processed by reducers synchronously. Usually, for any API request you'll want to dispatch at least three different kinds of actions...

Choosing whether to use a single action type with flags, or multiple action types, is up to you. It's a convention you need to decide with your team. Multiple types leave less room for a mistake, but this is not an issue if you generate action creators and reducers with a helper library like redux-actions.

Here is the doc link

like image 31
David Kayembe Avatar answered Sep 21 '22 19:09

David Kayembe