How to pass params with history.push/Link/Redirect in react-router v4?

Viewed 516299

How can we pass parameter with this.props.history.push('/page') in React-Router v4?

.then(response => {
       var r = this;
        if (response.status >= 200 && response.status < 300) {
             r.props.history.push('/template');
          });
13 Answers

Extending the solution (suggested by Shubham Khatri) for use with React hooks (16.8 onwards):

package.json (always worth updating to latest packages)

{
     ...

     "react": "^16.12.0",
     "react-router-dom": "^5.1.2",

     ...
}

Passing parameters with history push:

import { useHistory } from "react-router-dom";

const FirstPage = props => {
    let history = useHistory();

    const someEventHandler = event => {
       history.push({
           pathname: '/secondpage',
           search: '?query=abc',
           state: { detail: 'some_value' }
       });
    };

};

export default FirstPage;


Accessing the passed parameter using useLocation from 'react-router-dom':

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

const SecondPage = props => {
    const location = useLocation();

    useEffect(() => {
       console.log(location.pathname); // result: '/secondpage'
       console.log(location.search); // result: '?query=abc'
       console.log(location.state.detail); // result: 'some_value'
    }, [location]);

};

  1. For the earlier versions:

    history.push('/[pathToSomeWhere]', yourData);
    

    And get the data in the related component just like below:

    this.props.location.state // it is equal to yourData
    
  2. For the newer versions the above way works well but there is a new way:

    history.push({
      pathname: '/[pathToSomeWhere]',
      state: yourData,
    });
    

    And get the data in the related component just like below:

    • Class Component

      this.props.location.state; // it is equal to yourData
      
    • Function Component

      const location = useLocation();
      location.state; // it is equal to yourData
      

Sometime it will be needed to use Link or NavLink component instead of using history.push function. you can use like below:

<Link
  to={{
    pathname: '/[pathToSomeWhere]',
    state: yourData
  }}
> 
  ...
</Link>

Hint: the state key name should be used in the latest version.

you can use,

this.props.history.push("/template", { ...response }) or this.props.history.push("/template", { response: response })

then you can access the parsed data from /template component by following code,

const state = this.props.location.state

Read more about React Session History Management

If you need to pass URL params

theres a great post explanation by Tyler McGinnis on his site, Link to the post

here are code examples:

  1. on the history.push component:

    this.props.history.push(`/home:${this.state.userID}`)

  2. on the router component you define the route:

    <Route path='/home:myKey' component={Home} />

  3. on the Home component:

componentDidMount(){
    const { myKey } = this.props.match.params
    console.log(myKey )
}

React TypeScript with Hooks

From a Class

  this.history.push({
      pathname: "/unauthorized",
      state: { message: "Hello" },
    });

UnAuthorized Functional Component

interface IState {
  message?: string;
}

export default function UnAuthorized() {
  const location = useLocation();
  const message = (location.state as IState).message;

  return (
    <div className="jumbotron">
      <h6>{message}</h6>
    </div>
  );
}

Pass

history.push({pathname:"/yourroute",state: {_id: "0001", name: "AZ"}})

Read

import React from 'react';

const YourRoute = props=> {
    const { _id, name } = (props.location && props.location.state) || {};
        //_id and name will contain the passed data
     .
     .
     .

}

Here is a working example

I created a custom useQuery hook

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

const useQuery = (): URLSearchParams => {
  return new URLSearchParams(useLocation().search)
}

export default useQuery

Use it as

const query = useQuery();
const id = query.get("id") as string

Send it as so

history.push({  
 pathname: "/template",
 search: `id=${values.id}`,
});
                  

To use React 16.8 (withHooks) functional component you can use this way
We sending PhoneNumber to Next Page
Login.js

    import { useHistory } from 'react-router-dom';
    const history = useHistory();
        const handleOtpVerify=(phoneNumber)=>
          {
               history.push("/OtpVerifiy",{mobNo:phoneNumber})
          } 

<button onClick={handleOtpVerify}> Submit </button>

OtpVerify.js

    import  useLocation  from 'react-router-dom';
    const [phoneNumber, setphoneNumber] = useState("")
        useEffect(() => {
                setphoneNumber(location.state.mobNo)
            }, [location]);
    return (
    <p>We have sent Verification Code to your</p>
    <h1>{phoneNumber}</h1>
    )

react router dom version 6.2.1
useHistory() deprecated changed useNavigate()

import { useNavigate } from "react-router-dom";

 const navigate = useNavigate()
 
 onClick={() => { navigate('/OtpVerifiy',{mobNo:phoneNumber}) }} 

You can use location to send state to other component, like this

In your Source Component

this.props.history.push(pathComponent, sendState);

pathComponent is target component that will receive the state

In your Target Component you can receive the state like this if your use class component

  • Javascript version
constructor(props) {
  this.state = this.props.location.state
}
  • Typescript version
constructor(props: {}) {
  const receiveState = this.props.location.state as StateType // you must parse into your state interface or type
  this.state = receiveState
}

Bonus

If you want to reset the received state. Use history to replace the location, like this

this.props.history({pathName: currentPath, state: resetState})

currentPath is the Target Component path resetState is new value state whatever you want

It is not necessary to use withRouter. This works for me:

In your parent page,

<BrowserRouter>
   <Switch>
        <Route path="/routeA" render={(props)=> (
          <ComponentA {...props} propDummy={50} />
        )} />

        <Route path="/routeB" render={(props)=> (
          <ComponentB {...props} propWhatever={100} />
          )} /> 
      </Switch>
</BrowserRouter>

Then in ComponentA or ComponentB you can access

this.props.history

object, including the this.props.history.push method.

To use React 16.8+(withHooks) you can use this way

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

export default function SomeFunctionalComponent() {
let history = useHistory(); // should be called inside react component

const handleClickButton = () => {    
"funcionAPICALL"
       .then(response => {
             if (response.status >= 200 && response.status < 300) {
                 history.push('/template');
              });
}

return ( <div> Some component stuff 
    <p>To make API POST request and redirect to "/template" click a button API CALL</p>
    <button onClick={handleClickButton}>API CALL<button>
</div>)
} 

Source here to read more https://reacttraining.com/react-router/web/example/auth-workflow

Add on info to get query parameters.

const queryParams = new URLSearchParams(this.props.location.search);
console.log('assuming query param is id', queryParams.get('id');

For more info about URLSearchParams check this link URLSearchParams

Related