2

How can I access browserHistory on redux? I'm passing the browserHistory to a browserRouter from react-router. I want a reducer to listen for an action and the push another url. What's the best solution for this?

Tim Givois
  • 1,507
  • 11
  • 33

2 Answers2

1

First, you'll need to have access to the Route props like history, location, and match in a component. You will have these props automatically if the rendered component was created by a Route component from react-router. Otherwise, you will need to use withRouter from react-router to decorate your component with the Route props.

Example using withRouter:

// MyComponent before
import { connect } from 'react-redux'
const MyComponent = (props) => (<div>{props.message}</div>)
export default connect()(MyComponent)

// MyComponent after
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
const MyComponent = (props) => (<div>{props.message}</div>)
export default withRouter(connect()(MyComponent))

In the after example, MyComponent you will have access to history under props.history (or this.props.history if in a class component).

After you have access to history in your component, you can redirect the app using props.history.push('/a/new/url'). It sounds like you want to use it in an action to change the state. If that's the case, I recommend passing in your reference to history into the action as an argument. Here is an example of an action which creates a new Post and then redirects to a list view of Posts in the same category. Note: I'm using redux-thunk in this example in order to be able to dispatch async actions.

In my PostForm component, I create a variable for history:

const rrHistory = this.props.history

Later, I pass this variable into the createPost action when the Save button is clicked:

createPost(model.title, model.body, model.author, model.category, rrHistory)

Then in the action code, after some async stuff finishes with the API server, we use the rrHistory variable reference to redirect to the categories list view:

rrHistory.push(`/${postCategory}/${newPost.id}`)

Note, that this is a working example, but it is far from perfect. You can also check out this SO Answer for other navigation ideas Programmatically navigate using react router V4

Julian Soro
  • 3,530
  • 4
  • 25
  • 31
  • oh I see. So you are passing the history from the component to an action and then you push the route. Interesting, I will try it. I was looking for a more 'clean' solution, a way of connecting the store with the actual props of the component, and as history is basically a prop, access it and push the route. – Tim Givois Dec 15 '17 at 00:56
  • This is because, I'm creating an authentication system. So whenever you click a button, I use a React-Saga to authenticate the user. If successfull, then redirect to home page... But not sure how should I approach this. – Tim Givois Dec 15 '17 at 00:58
  • If the auth call is to the server, it seems like you'd doing something similar to what I did there – Julian Soro Dec 15 '17 at 00:59
  • Thanks, Julian. It seems ok, Ill guess Ill try to pass the history reference to an action! – Tim Givois Dec 15 '17 at 01:03
  • 2
    Tim, as an alternative, you can track your intention to redirect with some piece of state--either in the component's this.state or in the redux store, wherever makes more sense in your app--and use that state value to trigger a [Redirect](https://reacttraining.com/react-router/web/api/Redirect). For example, in render(): `{ isAuth ? : ( ) } ` – Julian Soro Dec 15 '17 at 01:32
  • Wow, I think this is a better solution. I was reading that redux reducers shouldn't have side effects, so my first approach is breaking this rule. So decisiones should be taken on the component or router checking the state first. Thanks! – Tim Givois Dec 15 '17 at 05:32
0
import { withRouter } from 'react-router-dom';
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Header));
slfan
  • 8,209
  • 115
  • 61
  • 73