6

I am moving a part of my app's state from the store to the URL.

I am currently using redux to manage my app's state along with reselect to create selectors. The selectors compute derived values from the state in the redux store (in principal, this is their only input).

Now part of the state will be contained within the URL instead, so I'm not sure how to go about reading it.

I have looked at react-router-redux, which at first glance may appear to be the solution (indeed, I can get to the value I want using state.routing.locationBeforeTransitions.query) but this doesn't seem to be the right way to do it, given that in their docs it says:

You should not read the location state directly from the Redux store.

Is there another way that I can access my location state, or should I just ignore this warning and use it in my selector?

Tom Fenech
  • 65,210
  • 10
  • 85
  • 122
  • do you need access to router's params from mapStateToProps? – Kokovin Vladislav Sep 21 '16 at 17:34
  • @Utro the selector is called from there but the idea is that you only pass the selector one argument, the state object. I guess I could add what I need from the router to the state object using ownProps... – Tom Fenech Sep 21 '16 at 17:46
  • there are ways: 1) geting ownProps.params in mapStateToProps 2) in component: passing `this.props.params.someparam` to action 3) using `redux-router` wich keeps your router state inside store. – Kokovin Vladislav Sep 21 '16 at 17:46
  • 1
    usually selectors can get two params : state and props. It is quite common https://github.com/reactjs/reselect#accessing-react-props-in-selectors – Kokovin Vladislav Sep 21 '16 at 17:48

1 Answers1

6

You are correct that the react-router-redux docs seem to recommend against getting your router state this way.

While Reselect selectors commonly only make use of the first argument (the state), they can actually take a second argument (the component's props). Inside these props you will find the params being passed by React Router (assuming they are being passed to the component you are trying to connect).

I have included a trivial example below where all I'm doing is upper-casing the location, but you can imagine making as complex a selector as you want that includes other selectors that use state to get things out of the Redux store.

const selectLocation = (_state, props) => props.location;
const selector = createSelector(
  selectLocation, 
  (location) => ({ upperCasedLocation: location.toUpperCase() })
);

const MySmartComponent = (props) => <div>{props.upperCasedLocation}</div>;

export default connect(selector)(MySmartComponent);
Rob Wise
  • 4,560
  • 3
  • 21
  • 30