830

How can I define a route in my routes.jsx file to capture the __firebase_request_key parameter value from a URL generated by Twitter's single sign on process after the redirect from their servers?

http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla

I tried with the following routes configuration, but the :redirectParam is not catching the mentioned param:

<Router>
  <Route path="/" component={Main}>
    <Route path="signin" component={SignIn}>
      <Route path=":redirectParam" component={TwitterSsoButton} />
    </Route>
  </Route>
</Router>
JensB
  • 839
  • 4
  • 19
Franco
  • 11,845
  • 7
  • 27
  • 33

47 Answers47

945

React Router v6, using hooks

In react-router-dom v6 there's a new hook named useSearchParams. So with

const [searchParams, setSearchParams] = useSearchParams();
searchParams.get("__firebase_request_key")

you will get "blablabla". Note, that searchParams is an instance of URLSearchParams, which also implements an iterator, e.g. for using Object.fromEntries etc.

React Router v4/v5, without hooks, generic

React Router v4 does not parse the query for you any more, but you can only access it via this.props.location.search (or useLocation, see below). For reasons see nbeuchat's answer.

E.g. with qs library imported as qs you could do

qs.parse(this.props.location.search, { ignoreQueryPrefix: true }).__firebase_request_key

Another library would be query-string. See this answer for some more ideas on parsing the search string. If you do not need IE-compatibility you can also use

new URLSearchParams(this.props.location.search).get("__firebase_request_key")

For functional components you would replace this.props.location with the hook useLocation. Note, you could use window.location.search, but this won't allow to trigger React rendering on changes. If your (non-functional) component is not a direct child of a Switch you need to use withRouter to access any of the router provided props.

React Router v3

React Router already parses the location for you and passes it to your RouteComponent as props. You can access the query (after ? in the url) part via

this.props.location.query.__firebase_request_key

If you are looking for the path parameter values, separated with a colon (:) inside the router, these are accessible via

this.props.match.params.redirectParam

This applies to late React Router v3 versions (not sure which). Older router versions were reported to use this.props.params.redirectParam.

General

nizam.sp's suggestion to do

console.log(this.props)

will be helpful in any case.

JBallin
  • 8,481
  • 4
  • 46
  • 51
Christian
  • 13,285
  • 2
  • 32
  • 49
  • 3
    It is not required to change the react router for it. – Christian Jun 01 '16 at 12:16
  • 2
    I wouldn't suggest using `console.dir()` due to [warning note](https://developer.mozilla.org/en-US/docs/Web/API/Console/dir) ...at least :) – boldnik Nov 21 '16 at 16:20
  • 1
    Well, it's just for looking at the contents, once. You can also just put a break point and evaluate this.props in the debugger. Nowadays, even console.log will do the job (at least in Chrome you can expand values printed like that) - and even console.log is nothing to use in production. – Christian Nov 22 '16 at 07:56
  • Do I have to use react router for this? I'm currently not using react router in my React app and don't have a need for it except one scenario. If there's another way to pick up some params from the URL without using react router, I'd love to do that. – Sam Jan 01 '17 at 00:25
  • @Sam: I expect you need it. But actually I don't know. Have you tested it meanwhile? – Christian Jan 13 '17 at 09:51
  • 2
    @Christian I ended up using just plain javascript. const path = window.location.pathname; gives me the URL. I can then parse it the way I need to. I placed this in componentWillMount life cycle event in my React component. – Sam Jan 13 '17 at 18:53
  • 1
    you may need `this.props.match.params.[field_name]` – vknyvz Apr 06 '17 at 23:59
  • @vknyvz Right, from the documentation linked by me that's correct. I'll leave the old one as well, as this was at least working in the past. – Christian Apr 07 '17 at 07:09
  • 7
    In `react-router-dom` I had to use `withRouter` to make this work! – demonofthemist Jun 19 '17 at 06:56
  • 1
    i think you can use `this.props.computedMatch.params.redirectParam` to make it work – Shan Sep 27 '19 at 12:11
  • Afaik computedMatch only reflects the route parameters. So it will work if you set it up like in that answer https://stackoverflow.com/a/45599016/969483. But if you use the query syntax (?) with other parameters it will not work. – Christian Sep 27 '19 at 12:49
  • 1
    Good answer, but there is no such option as `ignoreQueryPrefix` in `parse()` method, https://github.com/sindresorhus/query-string#parsestring-options. Mentioned option applies to `qs` library, not to `query-string`, which is used by you as an example. – mitenka Feb 11 '20 at 11:39
  • Thanks, you're right. Corrected the name and linked to the qs library, instead. – Christian Feb 11 '20 at 15:11
  • Is ```new URLSearchParams``` necessary? I have read that "new" should be avoided as much as possible. – Ishan Tomar Mar 23 '20 at 08:34
  • Afaik you will need to create an instance of URLSearchParams to use it, yes. But don't worry too much, in modern browser creating short-living objects is not a big issue any more. If you really do it millions of times, measure performance instead of guessing it might be bad. – Christian Mar 26 '20 at 09:48
  • FWIW you probably don't need to use qs or query-string anymore, according to caniuse.com [95% of users have native support for URLSearchParams](https://caniuse.com/?search=URLSearchParams) – Jordan Doyle May 03 '21 at 17:10
  • with React Router Dom V6, you can't use { useParams } hook in class component. – maverick Nov 28 '21 at 15:47
  • 1
    Generally, you cannot use hooks in class components, right? Is there a change/difference with React Router Dom V6? – Christian Nov 30 '21 at 16:16
  • No answer for v6. Any one please help me, for class component. I know hooks cannot be used in class, everyone is pointing this. – Sudhakar Krishnan Dec 06 '21 at 17:56
  • You can use the first/generic solution for v6 as well. – Christian Dec 07 '21 at 21:20
  • @Christian as your answer explicitly contains React Router v6 heading, it seems as it's the most up-to-date one. I'd suggest incorporating this solution: https://stackoverflow.com/posts/70125147/revisions to your answer as there's now an even better way for v6. :) – Martin D Dec 22 '21 at 16:19
264

React Router v4

Using component

<Route path="/users/:id" component={UserPage}/> 
this.props.match.params.id

The component is automatically rendered with the route props.


Using render

<Route path="/users/:id" render={(props) => <UserPage {...props} />}/> 
this.props.match.params.id

Route props are passed to the render function.

andromeda
  • 4,433
  • 5
  • 32
  • 42
spencer.sm
  • 19,173
  • 10
  • 77
  • 88
  • 2
    I had a similar issue accessing the ``query params`` of my app's current URL in a child component using React Router v4. If you're looking for the ``query params``, this.props.location.query in React Router 4 has been removed (currently using v4.1.1). See this answer: https://stackoverflow.com/a/43630848/1508105 – Alex Johnson Sep 22 '17 at 02:23
  • 84
    This does not answer the question unfortunately as you will not necessarily have `/users/?q=...` but you could have `/user?q=...`. You should use `this.props.location.search` in React Router v4 and parse the results yourself as explained in my answer below. – nbeuchat Jan 15 '18 at 03:46
  • This is the correct answer. `this.props.location.search` does not exist. – NickJ Mar 04 '19 at 02:56
  • @NickJ: which version of React Router do you use? – nbeuchat Mar 04 '19 at 14:43
  • @NickJ I use 'window.location.search' and it works great, fyi – Code True May 27 '22 at 14:08
190

React Router v3

With React Router v3, you can get query-string from this.props.location.search (?qs1=naisarg&qs2=parmar). For example, with let params = queryString.parse(this.props.location.search), would give { qs1 : 'naisarg', qs2 : 'parmar'}

React Router v4

With React Router v4, the this.props.location.query does not exist anymore. You need to use this.props.location.search instead and parse the query parameters either by yourself or using an existing package such as query-string.

Example

Here is a minimal example using React Router v4 and the query-string library.

import { withRouter } from 'react-router-dom';
import queryString from 'query-string';
    
class ActivateAccount extends Component{
    someFunction(){
        let params = queryString.parse(this.props.location.search)
        ...
    }
    ...
}
export default withRouter(ActivateAccount);

Rational

The React Router's team rational for removing the query property is:

There are a number of popular packages that do query string parsing/stringifying slightly differently, and each of these differences might be the "correct" way for some users and "incorrect" for others. If React Router picked the "right" one, it would only be right for some people. Then, it would need to add a way for other users to substitute in their preferred query parsing package. There is no internal use of the search string by React Router that requires it to parse the key-value pairs, so it doesn't have a need to pick which one of these should be "right".

[...]

The approach being taken for 4.0 is to strip out all the "batteries included" kind of features and get back to just basic routing. If you need query string parsing or async loading or Redux integration or something else very specific, then you can add that in with a library specifically for your use case. Less cruft is packed in that you don't need and you can customize things to your specific preferences and needs.

You can find the full discussion on GitHub.

Community
  • 1
  • 1
nbeuchat
  • 6,575
  • 5
  • 36
  • 50
168

As far as I know there are three methods you can do that.

1.use regular expression to get query string.

2.you can use the browser api. image the current url is like this:

http://www.google.com.au?token=123

we just want to get 123;

First

 const query = new URLSearchParams(this.props.location.search);

Then

const token = query.get('token')
console.log(token)//123
  1. use a third library called 'query-string'. First install it

    npm i query-string Then import it to the current javascript file:

    import queryString from 'query-string'

Next step is to get 'token' in the current url, do the following:

const value=queryString.parse(this.props.location.search);
const token=value.token;
console.log('token',token)//123

Updated on 25/02/2019

4. if the current url looks like the following:

http://www.google.com.au?app=home&act=article&aid=160990

we define a function to get the parameters:

function getQueryVariable(variable)
{
        var query = window.location.search.substring(1);
        console.log(query)//"app=article&act=news_content&aid=160990"
        var vars = query.split("&");
        console.log(vars) //[ 'app=article', 'act=news_content', 'aid=160990' ]
        for (var i=0;i<vars.length;i++) {
                    var pair = vars[i].split("=");
                    console.log(pair)//[ 'app', 'article' ][ 'act', 'news_content' ][ 'aid', '160990' ] 
        if(pair[0] == variable){return pair[1];}
         }
         return(false);
}

We can get 'aid' by:

getQueryVariable('aid') //160990
starball
  • 20,030
  • 7
  • 43
  • 238
MING WU
  • 2,962
  • 1
  • 12
  • 16
90

When using React hooks there is no access to access to this.props.location. To capture url parameters use window object.

const search = window.location.search;
const params = new URLSearchParams(search);
const foo = params.get('bar');
t-reksio
  • 3,251
  • 18
  • 12
  • You can use "useLocation" from "react-router-dom" instead of window object to achieve same results. – Saqib S Feb 11 '20 at 07:53
  • 1
    URLSearchParams Is not supported by IE https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility – Michael Freidgeim Feb 18 '20 at 20:50
  • Additionally, accessing window.location will not allow to trigger React's re-render on changes. – Christian Mar 18 '20 at 08:25
  • 1
    this answer is useful if you get location.search from react-router dom as is done in dsgriffin's answer – Dave Barnett Jul 21 '20 at 15:44
  • helpful your answer, thanks my king – jonathasborges1 Nov 04 '22 at 15:07
  • IE support is mostly irrelevant as Microsoft does not support IE 11 anymore. IE takes up less than .5% of all desktop browsers: https://www.lambdatest.com/web-technologies/urlsearchparams-support-on-ie-11 You can use `URLSearchParams` pretty freely – GavinBelson Mar 02 '23 at 16:01
88

React Router v4 no longer has the props.location.query object (see github discussion). So the accepted answer will not work for newer projects.

A solution for v4 is to use an outside library query-string to parse the props.location.search

const qs = require('query-string');
//or
import * as qs from 'query-string';

console.log(location.search);
//=> '?foo=bar'

const parsed = qs.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}
JTG
  • 8,587
  • 6
  • 31
  • 38
  • 4
    For some reason for me qs.parse results in: `{'?foo': 'bar'}` – Chris Nov 24 '17 at 17:28
  • 4
    @Chris `var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });` should fix it. Example found here: https://github.com/ljharb/qs – Alan Schapira Jan 18 '18 at 14:05
  • @Chris Or simply remove question mark: ```const parsed = qs.parse(location.search.replace('?', ''));``` – Nazarko Dec 15 '21 at 04:25
60

React Router 5.1+

5.1 introduced various hooks like useLocation and useParams that could be of use here.

Example:

<Route path="/test/:slug" component={Dashboard} />

Then if we visited say

http://localhost:3000/test/signin?_k=v9ifuf&__firebase_request_key=blablabla

You could retrieve it like

import { useLocation } from 'react-router';
import queryString from 'query-string';

const Dashboard: React.FC = React.memo((props) => {
    const location = useLocation();

    console.log(queryString.parse(location.search));

    // {__firebase_request_key: "blablabla", _k: "v9ifuf"}

    ...

    return <p>Example</p>;
}
dsgriffin
  • 66,495
  • 17
  • 137
  • 137
50

With this one-liner, you can use it anywhere in both React Hook and React Class Component with plain JavaScript.

https://www.hunterisgod.com/?city=Leipzig

let city = (new URLSearchParams(window.location.search)).get("city")
Hunter
  • 3,080
  • 20
  • 23
31

React Router v4

const urlParams = new URLSearchParams(this.props.location.search)
const key = urlParams.get('__firebase_request_key')

Please note that it is currently experimental.

Check browser compatibility here: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility

Mike Frenil L
  • 411
  • 4
  • 3
23

http://localhost:8000/#/signin?id=12345

import React from "react";
import { useLocation } from "react-router-dom";

const MyComponent = () => {
  const search = useLocation().search;
const id=new URLSearchParams(search).get("id");
console.log(id);//12345
}
Hassan Saeed
  • 6,326
  • 1
  • 39
  • 37
  • For even a simpler solution, I've created a 'useClearParams` hook to be used with function components, https://github.com/oyalhi/use-clear-params#readme if anyone is interested. – oyalhi Sep 21 '21 at 00:13
22

Not the react way, but I believe that this one-line function could help you :)

const getQueryParams = (query = null) => [...(new URLSearchParams(query||window.location.search||"")).entries()].reduce((a,[k,v])=>(a[k]=v,a),{});

or this:

const getQueryParams = (query = null) => (query||window.location.search.replace('?','')).split('&').map(e=>e.split('=').map(decodeURIComponent)).reduce((r,[k,v])=>(r[k]=v,r),{});

or full version:

const getQueryParams = (query = null) => {
  return (
    (query || window.location.search.replace("?", ""))

      // get array of KeyValue pairs
      .split("&") 

      // Decode values
      .map((pair) => {
        let [key, val] = pair.split("=");

        return [key, decodeURIComponent(val || "")];
      })

      // array to object
      .reduce((result, [key, val]) => {
        result[key] = val;
        return result;
      }, {})
  );
};

Example:
URL:  ...?a=1&b=c&d=test
Code:

getQueryParams()
//=> {a: "1", b: "c", d: "test"}

getQueryParams('type=user&name=Jack&age=22')
//=> {type: "user", name: "Jack", age: "22" }
Nazarko
  • 340
  • 3
  • 14
22

React Router Dom V6 https://reactrouter.com/docs/en/v6/hooks/use-search-params

import * as React from "react";
import { useSearchParams } from "react-router-dom";

function App() {
  let [searchParams, setSearchParams] = useSearchParams();

  function handleSubmit(event) {
    event.preventDefault();
    // The serialize function here would be responsible for
    // creating an object of { key: value } pairs from the
    // fields in the form that make up the query.
    let params = serializeFormQuery(event.target);
    setSearchParams(params);
  }

  return (
    <div>
      <form onSubmit={handleSubmit}>{/* ... */}</form>
    </div>
  );
}

Till React Router Dom V5

function useQueryParams() {
    const params = new URLSearchParams(
      window ? window.location.search : {}
    );

    return new Proxy(params, {
        get(target, prop) {
            return target.get(prop)
        },
    });
}

React hooks are amazing

If your url looks like /users?page=2&count=10&fields=name,email,phone

// app.domain.com/users?page=2&count=10&fields=name,email,phone

const { page, fields, count, ...unknown } = useQueryParams();

console.log({ page, fields, count })
console.log({ unknown })

In case of your query parameter contains hyphone ("-") or space (" ") then you can not unpack like { page, fields, count, ...unknown }

You'll need to go with treditional assignment like

// app.domain.com/users?utm-source=stackOverFlow

const params = useQueryParams();

console.log(params['utm-source']);
Yash Pokar
  • 4,939
  • 1
  • 12
  • 25
  • This response has a few problems, see [my answer](https://stackoverflow.com/a/67965934/4420543) for these improvements. I am sorry to see my edit did not get accepted. – andras Jun 14 '21 at 06:57
21

you can check the react-router, in simple,you can use the code to get query parameter as long as you defined in your router:

this.props.params.userId
TommyLike
  • 1,010
  • 11
  • 20
  • 33
    This not the *right* answer in the case of OP. `props.params` is for URL params (url segment prefixed with ':' in react router), `props.location.query` stores query string params (after the '?') and is what OP want. – Matthieu Harlé Jan 10 '17 at 23:28
19

If your Router is like this

<Route exact path="/category/:id" component={ProductList}/>

You will get that id like this

this.props.match.params.id
Milan Panigrahi
  • 546
  • 9
  • 11
  • Does anyone know how this works in React Router 5.0.1? this.props.match.params is always empty. – Mark A. Tagliaferro Oct 25 '19 at 08:02
  • 2
    @MarkA.Tagliaferro The prop is only avialable to components being rendered by a Route. If that is not the case for your component, you can access them by wrapping your component in the withRouter HOC. – Jimmy Longley Nov 03 '19 at 01:51
18

Say there is a url as follows

http://localhost:3000/callback?code=6c3c9b39-de2f-3bf4-a542-3e77a64d3341

If we want to extract the code from that URL, below method will work.

const authResult = new URLSearchParams(window.location.search); 
const code = authResult.get('code')
Senthuran
  • 1,583
  • 2
  • 15
  • 19
15

do it all in one line without 3rd party libraries or complicated solutions. Here is how

let myVariable = new URLSearchParams(history.location.search).get('business');

the only thing you need to change is the word 'business' with your own param name.

example url.com?business=hello

the result of myVariable will be hello

jerryurenaa
  • 3,863
  • 1
  • 27
  • 17
  • 3
    `history.location.search` not work in my case, Instead of I use `window.location.search` and its work perfectly. `new URLSearchParams(window.location.search).get('bussiness')` – Ankit24007 Apr 01 '21 at 19:24
14

React Router v5.1 introduced hooks:

For

<Route path="/posts/:id">
  <BlogPost />
</Route>

You can access params / id with hook:

const { id } = useParams();

More here.

Bear
  • 1,017
  • 1
  • 10
  • 23
  • Okay then how to use in class? – Sudhakar Krishnan Dec 06 '21 at 17:52
  • 1
    @SudhakarKrishnan You can't use it in class component, it is a hook. For class component try wrapping your Class Component into `withRouter` HOC, for example in export line: `export default withRouter(Component);` It allows you to access property called `match`, `location` and `history`. For more information look here: https://v5.reactrouter.com/web/api/withRouter – Bear Dec 14 '21 at 02:46
13

If you aren't getting the this.props... you were expecting based on the other answers, you may need to use withRouter (docs v4):

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux terminology) to the router.  
const TwitterSsoButton = withRouter(ShowTheLocation)  

// This gets around shouldComponentUpdate
withRouter(connect(...)(MyComponent))

// This does not
connect(...)(withRouter(MyComponent))
jtlindsey
  • 4,346
  • 4
  • 45
  • 73
13

I had a hard time solving this issue. If none of the above work you can try this instead. I am using the create-react-app

Requirements

react-router-dom": "^4.3.1"

Solution

At the location where router is specified

<Route path="some/path" ..../>

Add the parameter name that you would want to pass in like this

<Route path="some/path/:id" .../>

At the page where you are rendering some/path you can specify this to view the parameter name call id like this

componentDidMount(){
  console.log(this.props);
  console.log(this.props.match.params.id);
}

At the end where you export default

export default withRouter(Component);

Remember to include import

import { withRouter } from 'react-router-dom'

When console.log(this.props) you would be able what has been passed down. Have fun!

NarDd
  • 131
  • 1
  • 2
12

Actually there is no need to use 3rd party library. We can make with pure JavaScript.

consider the following URL:

https://example.com?yourParamName=yourParamValue

Now we get:

const url = new URL(window.location.href);
const yourParamName = url.searchParams.get('yourParamName');

In short

const yourParamName = new URL(window.location.href).searchParams.get('yourParamName')

Another Smart Solution (Recommended)

const params = new URLSearchParams(window.location.search);
const yourParamName = params.get('yourParamName');

In short

const yourParamName = new URLSearchParams(window.location.search).get('yourParamName')

NOTE:

use "getAll" instead of "get" for Params having multiple value

https://example.com?yourParamName[]=yourParamValue1&yourParamName[]=yourParamValue2

const yourParamName = new URLSearchParams(window.location.search).getAll('yourParamName[]')

Result will be like:

["yourParamValue1", "yourParamValue2"]
12

Try This

ReactJS

http://localhost:4000/#/amoos?id=101

// ReactJS
import React from "react";
import { useLocation } from "react-router-dom";

const MyComponent = () => {
    const search = useLocation().search;
    const id = new URLSearchParams(search).get("id");
    console.log(id); //101
}

// VanillsJS
const url = "http://localhost:4000/#/amoos?id=101"  // We can use 'window.location'

function getQuery(url, q) {
   return (url.match(new RegExp('[?&]' + q + '=([^&]+)')) || [, null])[1];
}

console.log(getQuery(url, "id"))
GMKHussain
  • 3,342
  • 1
  • 21
  • 19
8

React router from v4 onwards no longer gives you the query params directly in its location object. The reason being

There are a number of popular packages that do query string parsing/stringifying slightly differently, and each of these differences might be the "correct" way for some users and "incorrect" for others. If React Router picked the "right" one, it would only be right for some people. Then, it would need to add a way for other users to substitute in their preferred query parsing package. There is no internal use of the search string by React Router that requires it to parse the key-value pairs, so it doesn't have a need to pick which one of these should be "right".

Having included that, It would just make more sense to just parse location.search in your view components that are expecting a query object.

You can do this generically by overriding the withRouter from react-router like

customWithRouter.js

import { compose, withPropsOnChange } from 'recompose';
import { withRouter } from 'react-router';
import queryString from 'query-string';

const propsWithQuery = withPropsOnChange(
    ['location', 'match'],
    ({ location, match }) => {
        return {
            location: {
                ...location,
                query: queryString.parse(location.search)
            },
            match
        };
    }
);

export default compose(withRouter, propsWithQuery)
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
8

You can use the following react hook:

  1. Hook state updates if the url changes
  2. SSR: typeof window === "undefined", just checking window causes errors (try it out)
  3. Proxy object hides implementation, so undefined is returned instead of null

So this is the function to get the search param as object:

const getSearchParams = <T extends object>(): Partial<T> => {
    // server side rendering
    if (typeof window === "undefined") {
        return {}
    }

    const params = new URLSearchParams(window.location.search) 

    return new Proxy(params, {
        get(target, prop, receiver) {
            return target.get(prop as string) || undefined
        },
    }) as T
}

And then use it as hook like that:

const useSearchParams = <T extends object = any>(): Partial<T> => {
    const [searchParams, setSearchParams] = useState(getSearchParams())

    useEffect(() => {
        setSearchParams(getSearchParams())
    }, [typeof window === "undefined" ? "once" : window.location.search])

    return searchParams
}

If your url looks like this:

/app?page=2&count=10

You can just read it like this:

const { page, count } = useQueryParams();

console.log(page, count)
andras
  • 3,305
  • 5
  • 30
  • 45
  • In your last example, did you mean to destructure `count` instead of `fields`? or where did `fields` come from? – micnil Feb 24 '22 at 21:21
  • @micnil it seems there is indeed something wrong with this answer, `useQueryParams` does not even exist. I proposed another solution [for this answer](https://stackoverflow.com/a/65451140/4420543) that wasn't accepted and this answer was written after that. The edit history of that answer and this one should give you the full picture. Sorry I don't have time for this issue rn. Hope it helps. – andras Feb 24 '22 at 21:50
8

React Router v6

Source: Getting Query Strings (Search Params) in React Router

Use the new useSearchParams hook and the .get() method:

const Users = () => {
  const [searchParams] = useSearchParams();
  console.log(searchParams.get('sort')); // 'name'

  return <div>Users</div>;
};

With this approach, you can read one or a few params.

BONUS Get params as an object:

If you need to get all query string params at once, then we can use Object.fromEntries like this:

const Users = () => {
  const [searchParams] = useSearchParams();
  console.log(Object.fromEntries([...searchParams])); // ▶ { sort: 'name', order: 'asecnding' }
  return <div>Users</div>;
};

Read more and live demo: Getting Query Strings (Search Params) in React Router

Chilaxathor
  • 626
  • 1
  • 9
  • 10
7

this.props.params.your_param_name will work.

This is the way to get the params from your query string.
Please do console.log(this.props); to explore all the possibilities.

nizam.sp
  • 4,002
  • 5
  • 39
  • 63
7
componentDidMount(){
    //http://localhost:3000/service/anas
    //<Route path="/service/:serviceName" component={Service} />
    const {params} =this.props.match;
    this.setState({ 
        title: params.serviceName ,
        content: data.Content
    })
}
Mo.
  • 26,306
  • 36
  • 159
  • 225
Anas Alpure
  • 510
  • 5
  • 9
  • 4
    Welcome to Stack Overflow! Please don't answer just with source code. Try to provide a nice description about how your solution works. See: [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Thanks – sɐunıɔןɐqɐp Aug 03 '18 at 06:51
  • 1
    Probably going to get a 'data' is not defined no-undef – Tom Stickel Sep 18 '19 at 18:13
7

Maybe a bit late but this react hook can help you get/set values in URL query: https://github.com/rudyhuynh/use-url-search-params (written by me).

It works with or without react-router. Below is code sample in your case:

import React from "react";
import { useUrlSearchParams } from "use-url-search-params";

const MyComponent = () => {
  const [params, setParams] = useUrlSearchParams()
  return (
    <div>
      __firebase_request_key: {params.__firebase_request_key}
    </div>
  )
}
Rudy Huynh
  • 530
  • 4
  • 10
5

You could create simple hook for extracting search params from current location:

import React from 'react';
import { useLocation } from 'react-router-dom';

export function useSearchParams<ParamNames extends string[]>(...parameterNames: ParamNames): Record<ParamNames[number], string | null> {
    const { search } = useLocation();
    return React.useMemo(() => { // recalculate only when 'search' or arguments changed
        const searchParams = new URLSearchParams(search);
        return parameterNames.reduce((accumulator, parameterName: ParamNames[number]) => {
            accumulator[ parameterName ] = searchParams.get(parameterName);
            return accumulator;
        }, {} as Record<ParamNames[number], string | null>);
    }, [ search, parameterNames.join(',') ]); // join for sake of reducing array of strings to simple, comparable string
}

then you could use it inside your functional component like this:

// current url: http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla
const { __firebase_request_key } = useSearchParams('__firebase_request_key');
// current url: http://localhost:3000/home?b=value
const searchParams = useSearchParameters('a', 'b'); // {a: null, b: 'value'}
kajkal
  • 504
  • 5
  • 8
5

Maybe someone can help clarify why but if you're attempting to hit props to find location from a fresh install of Create React App on the App.js page you get:

TypeError: Cannot read property 'search' of undefined

Even though I have App.js as the home route:

<Route exact path='/' render={props => (

On App.js only, using window.location worked for me:

import queryString from 'query-string';
...
const queryStringParams = queryString.parse(window.location.search);
sigmapi13
  • 2,355
  • 3
  • 30
  • 27
4

In the component where you need to access the parameters you can use

this.props.location.state.from.search

which will reveal the whole query string (everything after the ? sign)

Rocco Ghielmini
  • 303
  • 5
  • 10
3

I used an external package called query-string to parse url parameter like so.

import React, {Component} from 'react'
import { parse } from 'query-string';

resetPass() {
    const {password} = this.state;
    this.setState({fetching: true, error: undefined});
    const query = parse(location.search);
    return fetch(settings.urls.update_password, {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Authorization': query.token},
        mode: 'cors',
        body: JSON.stringify({password})
    })
        .then(response=>response.json())
        .then(json=>{
            if (json.error)
                throw Error(json.error.message || 'Unknown fetch error');
            this.setState({fetching: false, error: undefined, changePassword: true});
        })
        .catch(error=>this.setState({fetching: false, error: error.message}));
}
Joe
  • 31
  • 2
3

When you work with react route dom then will empty object with for match but if you do the following code then it will for es6 component as well as it works directly for function component

import { Switch, Route, Link } from "react-router-dom";

<Route path="/profile" exact component={SelectProfile} />
<Route
  path="/profile/:profileId"
  render={props => {
    return <Profile {...props} loading={this.state.loading} />;
  }}
/>
</Switch>
</div>

This way you can get props and match params and profile id

This worked for me after a lot of research on es6 component.

Jayant Patil
  • 1,537
  • 2
  • 11
  • 18
3

in typescript, see snippet below for example:

const getQueryParams = (s?: string): Map<string, string> => {
  if (!s || typeof s !== 'string' || s.length < 2) {
    return new Map();
  }

  const a: [string, string][] = s
    .substr(1) // remove `?`
    .split('&') // split by `&`
    .map(x => {
      const a = x.split('=');
      return [a[0], a[1]];
    }); // split by `=`

  return new Map(a);
};

in react with react-router-dom, you can do

const {useLocation} from 'react-router-dom';
const s = useLocation().search;
const m = getQueryParams(s);

see example below

// below is the transpiled and minified ts functions from above
const getQueryParams=t=>{if(!t||"string"!=typeof t||t.length<2)return new Map;const r=t.substr(1).split("&").map(t=>{const r=t.split("=");return[r[0],r[1]]});return new Map(r)};
   
// an example query string
const s = '?arg1=value1&arg2=value2'

const m = getQueryParams(s)
console.log(m.get('arg1'))
console.log(m.get('arg2'))
console.log(m.get('arg3')) // does not exist, returns undefined
John
  • 4,786
  • 8
  • 35
  • 44
3

The link in the most accepted answer is dead, because SO won't let me comment, for ReactRouter v6.3.0 you can useParams hook

import * as React from 'react';
import { Routes, Route, useParams } from 'react-router-dom';

function ProfilePage() {
  // Get the userId param from the URL.
  let { userId } = useParams();
  // ...
}

function App() {
  return (
    <Routes>
      <Route path="users">
        <Route path=":userId" element={<ProfilePage />} />
        <Route path="me" element={...} />
      </Route>
    </Routes>
  );
}
rarara
  • 161
  • 1
  • 7
3

Easy destructuring assignment of URLSearchParams

Test try below:

1 Goto: https://www.google.com/?param1=apple&param2=banana

2 Right click the page > click Inspect > goto Console tab
then Paste the below code:

const { param1, param2 } = Object.fromEntries(new URLSearchParams(location.search));
console.log("YES!!!", param1, param2 );

Output:

YES!!! apple banana

You can extend the params like param1, param2 to as many as we like.

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
2

In React Router v4 only withRoute is correct way

You can get access to the history object’s properties and the closest 's match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)

https://reacttraining.com/react-router/web/api/withRouter

krystianj
  • 103
  • 2
  • 12
2

Use let { redirectParam } = useParams(); for if you're using the functional component

It's a class component

constructor (props) {  
        super(props);
        console.log(props);
        console.log(props.match.params.redirectParam)
}
async componentDidMount(){ 
        console.log(this.props.match.params.redirectParam)
}
Karthikeyan Ganesan
  • 1,901
  • 20
  • 23
2

in React-Router-Dom V5

function useQeury() {
 const [query, setQeury] = useState({});
 const search = useLocation().search.slice(1);

 useEffect(() => {
   setQeury(() => {
     const query = new URLSearchParams(search);
     const result = {};
     for (let [key, value] of query.entries()) {
       result[key] = value;
     }
     setQeury(result);
   }, [search]);
 }, [search, setQeury]);

 return { ...query };
}


// you can destruct query search like:
const {page , search} = useQuery()

// result
// {page : 1 , Search: "ABC"}

2

You can use this code to get params as an object. If there is no query params in url the object will be empty

let url = window.location.toString();
let params = url?.split("?")[1]?.split("&");
let obj = {};
params?.forEach((el) => {
  let [k, v] = el?.split("=");
  obj[k] = v.replaceAll("%20", " ");
});
console.log(obj);
1

Or perhaps something like this?

let win = {
  'location': {
    'path': 'http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla'
  }
}
if (win.location.path.match('__firebase_request_key').length) {
  let key = win.location.path.split('__firebase_request_key=')[1]
  console.log(key)
}
prabhu
  • 878
  • 9
  • 17
1

You can use this simple hook written in Typescript:

const useQueryParams = (query: string = null) => {      
    const result: Record<string, string> = {};
    new URLSearchParams(query||window.location.search).forEach((value, key) => {
      result[key] = value;
    });
    return result;
}

Usage:

// http://localhost:3000/?userId=1889&num=112
const { userId, num } = useQueryParams();
// OR
const params = useQueryParams('userId=1889&num=112');
Nolesh
  • 6,848
  • 12
  • 75
  • 112
1

In React 18, to get query parameters and re-render a component when they change, useSyncExternalStore can be combined with a proxy object. This solution does not require React Router:

import { useCallback, useMemo, useSyncExternalStore } from 'react';
type PushStateParameters = Parameters<typeof window.history.pushState>;
type Listener = () => void;

let urlParams = new URLSearchParams(window.location.search);

window.history.pushState = new Proxy(window.history.pushState, {
  apply: (fn, thisArg, pushStateArgs) => {
    urlParams = new URLSearchParams(pushStateArgs[2]);
    listeners.forEach((listener) => listener());
    return fn.apply(thisArg, pushStateArgs as PushStateParameters);
  },
});

const listeners = new Set<Listener>();

function subscribe(listener: Listener) {
  listeners.add(listener);
  return () => listeners.delete(listener);
}

export function useUrlParams() {
  return useSyncExternalStore(
    subscribe,
    useCallback(() => urlParams, [urlParams])
  );
}

export function useUrlParam(name: string) {
  return useSyncExternalStore(
    subscribe,
    useCallback(() => urlParams.get(name), [urlParams.get(name), name])
  );
}

In this instance, a proxy is created to intercept calls to pushState - the same could (also) be done for replaceState. Two hooks are then defined relying on useSyncExternalStore :

  1. useUrlParams returns the latest UrlSearchParams object instance. Components using this hook re-render whenever any query parameter is added / changed / removed via pushState.
  2. useUrlParam takes as a single input the name of a query parameters, and returns its string value (or null, if it does not exist in the URL). Components using this hook re-render only when a query parameter with that given name is added / changed / removed via pushState.
ErikWittern
  • 1,083
  • 9
  • 13
0

This one works fine for me

  const urlParams = new URLSearchParams(window.location.search);
  const lang = urlParams.get('lang');
CsAlkemy
  • 152
  • 1
  • 6
-1
export class ClassName extends Component{
      constructor(props){
        super(props);
        this.state = {
          id:parseInt(props.match.params.id,10)
        }
    }
     render(){
        return(
          //Code
          {this.state.id}
        );
}
-1

You also can use react-location-query package, example:

  const [name, setName] = useLocationField("name", {
    type: "string",
    initial: "Rostyslav"
  });

  return (
    <div className="App">
      <h1>Hello {name}</h1>
      <div>
        <label>Change name: </label>
        <input value={name} onChange={e => setName(e.target.value)} />
      </div>
    </div>
  );

name - to get value setName = to set value

This package has many options, read more in docs on Github

kitsoRik
  • 189
  • 3
  • 12
-3
let data = new FormData();
data.append('file', values.file);
double-beep
  • 5,031
  • 17
  • 33
  • 41
fatemeh kazemi
  • 516
  • 6
  • 10
-5

most simple solution!

in routing :

   <Route path="/app/someUrl/:id" exact component={binder} />

in react code :

componentDidMount() {
    var id = window.location.href.split('/')[window.location.href.split('/').length - 1];
    var queryString = "http://url/api/controller/" + id
    $.getJSON(queryString)
      .then(res => {
        this.setState({ data: res });
      });
  }
A.J
  • 139
  • 1
  • 1
  • 10