React-router: Listening to route changes

Created on 27 Nov 2014  路  4Comments  路  Source: ReactTraining/react-router

I was wondering what people thought about being able to listen to route changes. I'm working on a pagination implementation that has been a huge pain in the ass because I'm checking for route query changes in componentDidUpdate. Since EVERYTHING causes componentDidUpdate to fire I need to be super defensive in how I check for changes.

This is some code that checks to see if the page query param has changed.

componentDidUpdate: function(prevProps, prevState) {
  if (!this.state.isLoading && this.getActiveQuery().page != this.state.currentPage && this.state.currentPage > 0) {
    ...snip...
  }
}

The above isn't very intuitive or readable and is going to need a nice big dollop of comments so other developers (and future me) can understand it.

Now, if I could do something similar to the following I'd be in heaven.

  routeDidUpdate: function(prevParams, prevQuery) {
    if (this.getActiveQuery().page != prevQuery.page) {
      ...snip...
    }
  }

At least being able to do something like the following would help.

componentDidUpdate: function(prevProps, prevState) {
  if (prevProps.query.page != this.getActiveQuery().page) {
    ...snip...
  }
}

Is this in-scope for React Router? Is there another totally obvious way to do what I want to achieve without what I proposed above?

Most helpful comment

Router.run(routes, function(Handler, state) {
  React.render(<Handler query={state.query}/>, document.body);
});

// then do this in all the route handlers
<RouteHandler {...this.props}/>

// and now you can use `componentWillReceiveProps
componentWillReceiveProps: function(nextProps) {
  var sameQuery = this.props.query.page === nextProps.query.page;
}

All 4 comments

Is there another totally obvious way to do what I want to achieve without what I proposed above?

:grinning:

var prevParams, prevQuery;

Router.run(routes, function (Handler) {
  // This callback is your notification that the routes changed in some way.
  React.render(<Handler prevQuery={prevQuery} prevParams={prevParams}/>, document.body);
  prevParams = state.params;
  prevQuery = state.query;
});

@mjackson Thanks for the reply!

I just upgraded my entire app to use React Router 0.11 from 0.10. This had better be worth it! :wink:

How do I access prevQuery and prevParams in a component?

I was able to figure out how to access prevQuery and prevParams in the component.

I was able to accomplish what I was looking for with the following logic.

React.createClass({
  getInitialState: function() {
    selectedPage: this.getQuery().page
  },

  componentDidUpdate: function() {
    if (this.state.selectedPage !== this.getQuery().page) {
      this.setState({ selectedPage: this.getQuery().page });
      ...load data...
    }
  }
})

I was kind of hoping to avoid setting state as it's just one more thing to keep track of but overall this solution is WAY better than what I was doing before.

Thanks @mjackson for the help!

Router.run(routes, function(Handler, state) {
  React.render(<Handler query={state.query}/>, document.body);
});

// then do this in all the route handlers
<RouteHandler {...this.props}/>

// and now you can use `componentWillReceiveProps
componentWillReceiveProps: function(nextProps) {
  var sameQuery = this.props.query.page === nextProps.query.page;
}
Was this page helpful?
0 / 5 - 0 ratings