Add a loading indicator for a React-Redux app with Promise middleware

I am a newbie to react to contraction. I want to add the download text when the user clicked the search button and fired the text when returning data or completing an action. In a normal asynchronous function, I can simply toggle the isLoading flag before and after the call.

However, in my application, I am dispatching an action that returns "type" and "payload" which is a promise. A redux-prom middleware which then automatically transforms this payload and sends it to the reducer. In other words, the middleware executes the .en action for the promise behind the scenes and gives my reducer the correct data.

In this case, I'm not sure how to add the download text to my view, because as soon as I call this.props.getIdByName (this.state.value), I don't know when the data will be returned. The logical place for me would be inside the reducer, since this is when the data will come back. However, I believe it would be a bad thing because reducers shouldn't be doing this kind of task?

Inside my component, I have the following function to send

  handleSubmit(e) {
    e.preventDefault();
    this.props.getIdByName(this.state.value);
  }

      

Inside the actions / index.js file I have the following action generator

export function getIdByName(name) {
    const FIELD = '/characters'
    let encodedName = encodeURIComponent(name.trim());
    let searchUrl = ROOT_URL + FIELD + '?ts=' + TS + '&apikey=' + PUBLIC_KEY + '&hash=' + HASH + '&name=' + encodedName;
    const request = axios.get(searchUrl)

    return {
        type: GET_ID_BY_NAME,
        payload: request
    }
}

      

Inside my gearboxes / gearboxes .jsx

export default function (state = INITIAL_STATE, action) {
    switch (action.type) {
        case GET_ID_BY_NAME: 
            console.log(action.payload.data.data.results[0].id); <-- here the data comes back correctly because reduer called the promise and gave back the data for me
            return {...state, id: action.payload.data.data.results[0].id};
        default:
            return state;
    }
}

      

And in my main index.js file I have a repository created with the following middleware

const createStoreWithMiddleware = applyMiddleware(
    promise,
    thunk
)(createStore);

      

+3


source to share


3 answers


When you dispatch an activity with Promise

as your payload when used redux-promise

, the middleware redux-promise

will catch the activity, wait for it to Promise

be canceled or rejected, and then retransmit the activity, now with the result Promise

as the payload. This means that you are still dealing with your actions, and also that once you are dealing with it, you know it. So you are correct that a reducer is the right place to do this.

However, you are also correct that reducers should not have side effects. They should only build a new state. Then the answer is to show and hide the loading indicator, changing your application state in Redux :)

We can add a flag with a name isLoading

to our Redux store:



const reducers = {
    isLoading(state = false, action) {
        switch (action.type) {
          case 'START_LOADING':
            return true;
          case 'GET_ID_BY_NAME':
            return false;
          default:
            return state;
        }
    },
    // ... add the reducers for the rest of your state here
}

export default combineReducers(reducers);

      

Whenever you are about to call getIdByName

, dispatch an action with a type before calling 'START_LOADING'

. When getIdByName

re-sent with help redux-promise

, you will know that the download is complete and the flag isLoading

will be set to false.

We now have a flag indicating whether we are uploading data to our Redux store. Using this flag, you can conditionally display a loading progress bar. :)

+1


source


I'm sure Pedro's answer should start, but I recently did a very accurate one loader/pre-loader

in my application.

The easiest way to do this.



  • Create a new key in an object state

    in one of your reducers and name it showLoader: false

    .
  • In the same container as before (the one with the button), create mapStateToProps

    and get this state property showLoader

    .
  • Inside container

    that contains the button you are trying to call with loader

    , add an event onClick

    that triggers action

    , say displayLoader

    . In the same function, also set the parameter this.props.showLoader

    totrue

  • Create an action displayLoader

    to write something like this:

    function displayLoader() {
        return {
            type: DISPLAY_LOADER,
            payload: {}
        }
    }
    
          

  • In gearboxes, catch this action and set showLoader

    back to false

    when your desired one is received payload

    .

Hope it helps!

0


source


I think we won't be able to rationally handle the load status with redux-prom, because redux-promise doesn't provide a mechanism to handle the middle situation from the very beginning of the promise to the end of the promise. I think we should abandon the use of redux promise for conveniently showing / hiding UI loading. We may need to use middleware like redux-loading-promise-middleware .

-1


source







All Articles