Search code examples
reactjsreduxreact-routerreact-reduxreact-router-redux

Is it a good idea to use browserhostory.push in action helpers?


In my React App I need to take decision based on data I receive from the server.

  1. If data is expected ( Dispatch actions to update state)
  2. If data has error tag ( browserhistory.push('/notfound'); )
  3. If expected data is unable to parsed ( browserhistory.push('/error');)

In my app structure, I am using Redux, React-Router and React-redux-Router libraries but no middleware. I have made actionHelpers to making ajax calls and then dispatch appropriate actions using Action Creator. These actionHelper methods are exposed in Components to change state. My Questions:

  1. What's the best way to handle these scenarios ?
  2. Is actionHelper the best place to take these decisions ?

I don't want to use any middleware for now but please let me know if its a good idea to use middleware to handle these scenarios.


Solution

  • Actions are not the place where you should do redirections. This behavior should be implemented in the component itself and actions should be left to update the store.

    You may want to use the Redux-thunk middleware here which allows you to dispatch a function (which receives dispatch as an argument instead of the object actions. You can then wrap that function in a promise and use it in componentWillMount.

    In your actions file:

    updateReduxStore(data) {
      return { 
          type: SOME_TYPE,
          payload: data.something
      };
    }
    
    fetchAndValidateData() {
      ...
    }
    
    checkData() {
        return function(dispatch) {
            return new Promise((resolve, reject) => {
                fetchAndValidateData().then((data) => {
                    try {
                        if (JSON.parse(data).length > 0) {
                            dispatch(updateReduxStore(data));
                            resolve('valid data');
                        } else if (data.error) {
                            reject('error in data');
                        }
                    }
                    catch(err) {
                      reject('malformed data');
                    }
                });
            });
        };
    }
    

    Then in your component:

    componentWillMount() {
        this.props.checkData()
          .then((message) => {
              console.log(message); //valid data
          })
          .catch((err) => {
              if (err === 'error in data') {
                  browserHistory.push('/notfound');
              } else if (err === 'malformed data') {
                  browserHistory.push('/error');
              }
          });
    }
    

    Redux-thunk middleware is made for such use cases.