7

According to the accepted answer to this question, React Router 4 doesn't match query parameters anymore. If I go from a URL matched by one of my <Route>s to the same URL with a different query string, the content doesn't seem to change. I believe this is because navigating between URLs that match the same <Route> doesn't change the content, but please correct me if I'm wrong. Given this, how do I use React Router for a set of URL's that need to differ only by query parameter?

For example, many search engines and other sites that use search bars, including the site I am working on, use a query parameter, commonly q or query. The user may search for one thing, then decide that is not what he/she wants and search for another thing. The user may type in the second URL or search with the search bar again. There isn't really a place for the search term in the URL path, so it kind of needs to go in the query string. How do we handle this situation?

Is there a way, with React Router, to link to a URL that only differs in the query string and change the content, without refreshing the entire page? Preferably, this wouldn't require any external library besides React and React Router.

trysis
  • 7,124
  • 12
  • 47
  • 74
  • can u provide some code so i ts easier to see what your trying to do – Omar Apr 09 '18 at 01:06
  • Sorry, I was doing this on my phone at night while going home from vacation. (I wasn't the one driving.) My components are also just a little more complex than react tutorials, but I will try to get a demo up. – trysis Apr 09 '18 at 23:40

2 Answers2

5

Try the render function prop instead of component prop of Route. Something like this:

<Route render={props => {
  // look for some param in the query string...
  const useComponentA = queryStringContains('A');
  if(useComponentA) {
    return <ComponentA {...props}/>;
  } else {
    return <ComponentB {...props}/>;
  }
}}/>
PanJunjie潘俊杰
  • 3,190
  • 1
  • 13
  • 22
  • I am doing this with some other components. I didn't think about it for this situation. Even if I did, I wouldn't have thought it would work, but it does! – trysis Apr 10 '18 at 00:15
  • 1
    @AmerllicA I don't quite understand you, are you asking whether my answer actually works? I didn't use this myself, you can ask the OP how this goes in his project. – PanJunjie潘俊杰 Jul 17 '18 at 03:17
  • what is this queryStringContains method? which file are you importing it from? react-router? – theprogrammer Mar 04 '21 at 17:09
  • @theprogrammer It's some pseudo code, means you should expand it to a few lines which do what this function name describes. To be more direct, swap out `queryStringContains('A')` with something like `window.location.search.includes('A')` – PanJunjie潘俊杰 Mar 05 '21 at 06:05
5

There are 2 ways to do that:

1) Use location.search in react component to get the query string, then pass it to child component to prevent re-rendering the whole component. React-router has the official example about this.

2) Define a regex path of router to catch the query string, then pass it to react component. Take pagination as an example:

routes.js, for router config you can refer this

const routerConfig = [
  {
    path: '/foo',
    component: 'Foo',
  },
  {
    path: '/student/listing:pageNumber(\\?page=.*)?',
    component: 'Student'
  },

Student.js

  render() {
    // get the page number from react router's match params
    let currentPageNumber = 1;
    // Defensive checking, if the query param is missing, use default number.
    if (this.props.match.params.pageNumber) {
      // the match param will return the whole query string, 
      // so we can get the number from the string before using it.
      currentPageNumber = this.props.match.params.pageNumber.split('?page=').pop();
    }
    return <div> 
             student listing content ...
             <Pagination pageNumber = {currentPageNumber}> 
           </div>
  }

Pagination.js

render() {
    return <div> current page number is {this.props.pageNumber} </div>
  }

The 2nd solution is longer but more flexible. One of the use cases is server sider rendering:

Apart from the react components, the rest of the application (e.g. preloaded saga) need to know the url including query string to make API call.

Eric Tan
  • 977
  • 9
  • 11