Search code examples
react-nativereduxreact-routerreact-router-reduxredux-loop

React Router with Redux Loop - Reducers may not dispatch actions


I'm trying to navigate to the previous screen after a redux action. I'm using react-router with react-router-redux and redux-loop.

Here's the scenario:

  1. On the home screen that there's a list of users /home.
  2. Tap on a user to go to their profile /home/profile/1234.
  3. Edit users name and tap save this.props.dispatch(UserState.updateUser(id, user, history).
  4. Once the user is updated successfully, go back to the home screen /home.

Here's some code:

View:

saveProfile = () => {
  const user = {
    name: this.state.name
  }
  this.props.dispatch(UserState.updateUser(this.state.id, user, this.props.history))
}

Action:

export function updateUser(id, user, history) {
  return {
    type: UPDATE_USER,
    payload: {
      id,
      user,
      history
    }
  }
}

Reducer:

case UPDATE_USER:
  return loop(
    state.updateIn(['users', action.payload.id], user => user.merge(fromJS(action.payload.user))),
    Effects.constant(action.payload.history.goBack())
  )

This results in an error Reducers may not dispatch actions.

On a different project, I've used redux-saga and was able to successfully pass the history object to the saga and push/goBack. There seems to be something going on with trying to pass the history object and calling it within redux-loop

I'm working on a POC for an updated navigation system for an existing production app, so working with redux-loop is required.

Any tips/help would be greatly appreciated. Please let me know if I'm missing any code that would be helpful.


Solution

  • I think @bradford-medeiros is correct about the problem being with

    Effects.constant(action.payload.history.goBack())

    That's a side effect, so it should not happen in a reducer. You should not need to pass around the history object.

    Not sure what version of react-router-redux you have, but there are typically actions exposed by it that can cause the changes you want.

    import {goBack} from 'react-router-redux';
    
    
    //in reducer
    return loop(
       state.updateIn(['users', action.payload.id], user => user.merge(fromJS(action.payload.user))),
       Effects.constant(goBack())
    );