4

i wanted to show loader for each and every request individually depending on what request made,Suppose in dashboard i have muiltple widget and they all have different api call, i wanted to show different loader for each request made,

one way is to make adding isLoading flag for every request made,which i think is not the good solution as the application grows,and i am finding solution that can handle multiple request from one flag

so how should i do to make dynamic individual loader based on every request

below is my reducer and action

reducer

export const intialstate = {
isAuth: false,
isLoading: false,
btnDisable: false
};

export default function(state = intialstate, action) {
switch (action.type) {
    case API_REQUEST:
        return {
            ...state,
            isLoading: true,
        };
    case API_SUCCESS:
        return {
            ...state,
            isLoading: false,
            isError: null
        };
    case API_FAILURE:
        return {
            ...state,
            isError: action.payload,
            isLoading: false,
        };
    // no default
 }
 return state;
}

action.js

export const AnyAPIRequest = () => {
return (dispatch) => {
    dispatch({
        type: API_REQUEST
    });

    API.anygetcall()
        .then((res) => {
            dispatch({
                type: API_SUCCESS
            });

            dispatch({ type: GETLIST, payload: res });
        })
        .catch((err) => {
            dispatch({
                type: API_FAILURE,
                payload: err
            });
        });
};
};

Please help,how to implement dynamic loader based on different request and let me know any thing to update in current workflow

4
  • why dont you keep global state in store and toggle it on success and failure of every request Commented May 14, 2018 at 8:29
  • 1
    If you want just a single flag, you could instead use an integer counter. When a request starts, increment the counter. When a request completes or fails, decrement the counter. If the counter is greater than 0, you know you have pending requests. Commented May 14, 2018 at 8:34
  • or you can also create an array of flag, globally, marking the names of the API calls, and remove it from the array once the request completed. this way, you can create loading animation for different api calls. Commented May 14, 2018 at 8:39
  • @ross-allen ok, but can you show any example Commented May 14, 2018 at 11:35

2 Answers 2

7

Two ways:

  1. Have an integer count of API calls loading. IsLoading: IsLoading + 1 and then show the loading indicator if IsLoading > 1
  2. Name each of your IsLoading differently to show different loading indicators. For example if you had a call to get students and a call to get teachers, you would have IsLoadingStudents and IsLoadingTeachers and have separate loading indicators for each component in the app
Sign up to request clarification or add additional context in comments.

3 Comments

i prefer approach 1,but how can i know that for which loader is loading, in respect to which api,suppose oncomponentmount there are 5 widget with 5 different api call, and suppose 1 api is student,2 api is teacher and so on...,and if student api is takes longer than teacher api to load then,loader will be shown to both api untill the student api get completed,so how to ensure that student only show loader and teacher display its component,can you please show me any example
you will need to use approach 2
I just published a package for this scenario, hopefully it could help? npmjs.com/package/react-multi-busy
5

If you don't want to add a new isLoadingXXX for each new API request, you can use a collection and give each API request a string ID. Something like the following:

Reducer:

export const intialstate = {
  isAuth: false,
  isLoadingRequestIds: [],
  btnDisable: false
};

export default function(state = intialstate, action) {
switch (action.type) {
    case API_REQUEST:
        return {
            ...state,
            isLoadingRequestIds: [...state.isLoadingRequestIds, action.requestId],
        };
    case API_SUCCESS:
        return {
            ...state,
            isLoadingRequestIds:
                state.isLoadingIds.splice(state.isLoadingRequestIds.indexOf(action.requestId)).slice(),
            isError: null
        };
    case API_FAILURE:
        return {
            ...state,
            isError: action.payload,
            isLoadingRequestIds:
                state.isLoadingIds.splice(state.isLoadingRequestIds.indexOf(action.requestId)).slice(),
        };
    // no default
}
return state;
}

Actions:

export const AnyAPIRequest = (requestId) => {
  return (dispatch) => {
      dispatch({
          requestId,
          type: API_REQUEST
      });

      API.anygetcall()
          .then((res) => {
              dispatch({
                  requestId,
                  type: API_SUCCESS
              });

              dispatch({ type: GETLIST, payload: res });
          })
          .catch((err) => {
              dispatch({
                  requestId,
                  type: API_FAILURE,
                  payload: err
              });
          });
  };
};

export const StudentAPIRequest = () => AnyAPIRequest('student');
export const TeacherAPIRequest = () => AnyAPIRequest('teacher');

3 Comments

thanks for the solution,i think you have by mistake written ...state.isLoadingIds instead of ...state.isLoadingRequestIds
and how do use in component for showing loading indicator for student like creating hoc
@tapandave I corrected the isLoadingRequestIds reference error that you noticed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.