94

I'm using react-router-dom 4.0.0-beta.6 in my project. I have a code like following:

<Route exact path="/home" component={HomePage}/>

And I want to get query params in HomePage component. I've found location.search param, which looks like this: ?key=value, so it is unparsed.

What is the right way to get query params with react-router v4?

andrfas
  • 1,192
  • 1
  • 9
  • 14

10 Answers10

193

The ability to parse query strings was taken out of V4 because there have been requests over the years to support different implementation. With that, the team decided it would be best for users to decide what that implementation looks like. We recommend importing a query string lib. Here's one that I use

const queryString = require('query-string');

const parsed = queryString.parse(props.location.search);

You can also use new URLSearchParams if you want something native and it works for your needs

const params = new URLSearchParams(props.location.search);
const foo = params.get('foo'); // bar

You can read more about the decision here

Tyler McGinnis
  • 30,798
  • 16
  • 69
  • 74
  • 12
    Do not use URLSearchParams without a polyfill. As of March 2018 Googlebot uses Chrome 41 (https://developers.google.com/search/docs/guides/rendering) which does not support URLSearchParams and your app will break if used in a critical path (https://caniuse.com/#feat=urlsearchparams). – Joshua Robinson Mar 14 '18 at 16:34
16

The given answer is solid.

If you want to use the qs module instead of query-string (they're about equal in popularity), here is the syntax:

const query = qs.parse(props.location.search, {
  ignoreQueryPrefix: true
})

The ignoreQueryPrefix option is to ignore the leading question mark.

Sergey Brunov
  • 11,755
  • 7
  • 39
  • 71
fisch2
  • 1,786
  • 1
  • 19
  • 22
  • 1
    Nice. in January 2019, qs has 12 million weekly downloads vs 2.7 million for query-string. – oyalhi Jan 05 '19 at 05:47
13

Another useful approach could be to use the out of the box URLSearchParams like this;

  let { search } = useLocation();

   const query = new URLSearchParams(search);
   const paramField = query.get('field');
   const paramValue = query.get('value');

Clean, readable and doesn't require a module. More info below;

user10750437
  • 246
  • 3
  • 10
6

The accepted answer works well but if you don't want to install an additional package, you can use this:

getUrlParameter = (name) => {
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    let regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
    let results = regex.exec(window.location.search);
    return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
  };

Given http://www.google.co.in/?key=value

getUrlParameter('key');

will return value

Julian
  • 7,968
  • 6
  • 50
  • 85
kartikag01
  • 1,389
  • 1
  • 17
  • 35
  • Thanks a ton mate.. the “query-string” library did not work for me for some reason, but your solution worked like a charm. I was using "react-dom": "^16.0.0", "react-router": "^4.2.0", "react-router-dom": "^4.2.2" and "query-string": "^5.0.1", – Rohan_Paul Dec 03 '17 at 06:02
  • this only assumes you have a single parameter in your querystring. The OP clearly asks for how to get query params - and that's what the npm modules mentioned do. Turn this into a function that returns an object of key/value pairs from the query string and that would be _really_ useful ! – Andy Lorenz May 02 '18 at 14:44
  • @AndyLorenz this even works when you have multiple query params, call given function with key whose value you wants to get. Yes method also can be transformed to give map of key values. – kartikag01 May 03 '18 at 16:51
  • that would work but not a good solution @Kartik_Agarwal. (a) It would require multiple executions of essentially the same (potentially expensive) code, (b) separate variables would need to be used for each parameter, whereas ideally you would populate an object of key/value pairs, (c) it requires you to know your parameter names, and additional checking to see whether they exist or not. If this was my code I'd look for a regex that can pick up all parameters iteratively, but I have to admit regexs make my ears bleed! – Andy Lorenz May 25 '18 at 17:13
5

I was researching about params for react router v4, and they didn't use it for v4, not like react router v2/3. I'll leave another function - maybe somebody will find it helpful. You only need es6 or plain javascript.

function parseQueryParams(query) {
  //You get a '?key=asdfghjkl1234567890&val=123&val2&val3=other'
  const queryArray = query.split('?')[1].split('&');
  let queryParams = {};
  for (let i = 0; i < queryArray.length; i++) {
    const [key, val] = queryArray[i].split('=');
    queryParams[key] = val ? val : true;
  }
  /* queryParams = 
     {
      key:"asdfghjkl1234567890",
      val:"123",
      val2:true,
      val3:"other"
     }
  */
  return queryParams;
}

Also, this function can be improved

ekhumoro
  • 98,079
  • 17
  • 183
  • 279
Xopsy
  • 71
  • 1
  • 4
2

Eh?

queryfie(string){
    return string
        .slice(1)
        .split('&')
        .map(q => q.split('='))
        .reduce((a, c) => { a[c[0]] = c[1]; return a; }, {});
}

queryfie(this.props.location.search);
Faheem
  • 867
  • 7
  • 24
0

I just made this so don't need to change the whole code structure(where you use query from redux router store) if you update to react router v4 or higher from a lower version.

https://github.com/saltas888/react-router-query-middleware

  • 1
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](http://meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted](http://stackoverflow.com/help/deleted-answers). – mrun Mar 23 '18 at 09:58
0

Here is a way without importing any additional libraries

const queryString = (string) => {
  return string.slice(1).split('&')
    .map((queryParam) => {
      let data = queryParam.split('=')
      return { key: data[0], value: data[1] }
    })
    .reduce((query, data) => {
      query[data.key] = data.value
      return query
    }, {});
}

const paramData = (history && history.location && history.location.search)
                ? parseQueryString(history.location.search)
                : null;
-3

Very easy

just use hook useParams()

Example:

Router:

<Route path="/user/:id" component={UserComponent} />

In your component:

export default function UserComponent() {

  const { id } = useParams();

  return (
    <>{id}</>
  );
}
CommonSenseCode
  • 18,848
  • 28
  • 112
  • 163
  • 1
    This doesn't work for the use case described in the question (at least not with React-Router v4 : https://reactrouter.com/web/api/Hooks/useparams) useParams only exposes the path params, not the search params. – Bennit Oct 26 '20 at 14:22
-4

Without need of any package:

const params = JSON.parse(JSON.stringify(this.props.match.params));

Then you can reach the related parameters with params.id