[reactjs] React - How to get parameter value from query string?

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>

This question is related to reactjs react-router

The answer is


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')

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)


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.


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);

Or perhaps something like this?

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


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))

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.


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


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.


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!


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

_x000D_
_x000D_
// 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
_x000D_
_x000D_
_x000D_


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>
  )
}

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


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

3. 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

Hope it helps.

Updated on 25/02/2019

  1. 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

export class ClassName extends Component{
      constructor(props){
        super(props);
        this.state = {
          id:parseInt(props.match.params.id,10)
        }
    }
     render(){
        return(
          //Code
          {this.state.id}
        );
}

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');

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


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


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.


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'}

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


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 });
      });
  }

let data = new FormData();
data.append('file', values.file);

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'}

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")

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}));
}

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

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
    })
}

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

const getQueryParams = () => window.location.search.replace('?', '').split('&').reduce((r,e) => (r[e.split('=')[0]] = decodeURIComponent(e.split('=')[1]), r), {});

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

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

export default function useQueryParams() {
  const params = new URLSearchParams(window.location.search)

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

React hooks are amazing


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.


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>;
}

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)

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to react-router

React : difference between <Route exact path="/" /> and <Route path="/" /> You should not use <Link> outside a <Router> React Router Pass Param to Component Detect Route Change with react-router What is the best way to redirect a page using React Router? No restricted globals React-router v4 this.props.history.push(...) not working How to pass params with history.push/Link/Redirect in react-router v4? How to use Redirect in the new react-router-dom of Reactjs How to implement authenticated routes in React Router 4?