391

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');
          });
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
IshanGarg
  • 3,987
  • 4
  • 11
  • 10

13 Answers13

561

First of all, you need not do var r = this; as this in if statement refers to the context of the callback itself which since you are using arrow function refers to the React component context.

According to the docs:

history objects typically have the following properties and methods:

  • length - (number) The number of entries in the history stack
  • action - (string) The current action (PUSH, REPLACE, or POP)
  • location - (object) The current location. May have the following properties:

    • pathname - (string) The path of the URL
    • search - (string) The URL query string
    • hash - (string) The URL hash fragment
    • state - (string) location-specific state that was provided to e.g. push(path, state) when this location was pushed onto the stack. Only available in browser and memory history.
  • push(path, [state]) - (function) Pushes a new entry onto the history stack
  • replace(path, [state]) - (function) Replaces the current entry on the history stack
  • go(n) - (function) Moves the pointer in the history stack by n entries
  • goBack() - (function) Equivalent to go(-1)
  • goForward() - (function) Equivalent to go(1)
  • block(prompt) - (function) Prevents navigation

So while navigating you can pass props to the history object like

this.props.history.push({
  pathname: '/template',
  search: '?query=abc',
  state: { detail: response.data }
})

or similarly for the Link component or the Redirect component

<Link to={{
      pathname: '/template',
      search: '?query=abc',
      state: { detail: response.data }
    }}> My Link </Link>

and then in the component which is rendered with /template route, you can access the props passed like

this.props.location.state.detail

Also keep in mind that, when using history or location objects from props you need to connect the component with withRouter.

As per the Docs:

withRouter

You can get access to the history object’s properties and the closest <Route>'s match via the withRouter higher-order component. withRouter will re-render its component every time the route changes with the same props as <Route> render props: { match, location, history }.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 3
    yes, that worked.Thanks! But not sure why `this.props.history.push('/template',response.data)` not working. According to docs of `push(path, [state])`, don't you think it should work? – Sanket Patel Dec 23 '18 at 09:07
  • 1
    Thanks for this! In my case I was only passing history directly, so I accessed my prop via this.props.history.location.state.propName - – Nunchucks Apr 08 '19 at 07:12
  • 1
    @SanketPatel you need to do this this.props.history.push('/template', {response: response.data}) – Nauman Moazzam Jan 07 '20 at 09:48
  • Is it possible to open the route in a new tab while passing data in the state variable when navigating you can pass props to the history object? – Gaurav Kumar Jan 31 '20 at 13:49
  • 4
    what about goBack() ? when navigating back with goBack(), I cannot see any of the history states in either props.location or props.history.location. Navigating forwards with push() it works fine – MariusB Feb 12 '20 at 13:11
  • In "react-router-dom": "^5.1.2" putting 'state' inside the object causes error. we can put any valid name like 'data' instead of 'state'. So it will be like, My Link – Debotos Das Mar 26 '20 at 14:00
  • After refreshing the page, state values were getting lost. Any solution for that? – Mahendra Kulkarni May 03 '20 at 12:17
  • @MariusB only `push` and `replace` support a state object. – Jeremy May 18 '20 at 09:44
  • Tip of the day ⚠ - react - redux - react-router-dom: If you are watching location in some useEffect function, don't forget to resend your "queryParams" to avoid refreshing state lol – JORGE GARNICA Oct 28 '21 at 22:43
177

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

};

Branislav Lazic
  • 14,388
  • 8
  • 60
  • 85
akhouri
  • 3,065
  • 3
  • 25
  • 29
102
  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.

AmerllicA
  • 29,059
  • 15
  • 130
  • 154
51

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

Tenusha Guruge
  • 2,147
  • 3
  • 18
  • 38
  • This logic worked for me while history.push with back_url in state this.props.history.push(redirect_url,{ back_url: '/needing_url' }); and getting this at landing page by this.props.location.state.back_url – Braham Dev Yadav May 27 '20 at 13:11
14

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 )
}
Diamond
  • 3,470
  • 2
  • 19
  • 39
shyke
  • 194
  • 1
  • 5
12

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>
  );
}
Devgig
  • 141
  • 1
  • 3
12

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

Abdulhakim Zeinu
  • 3,333
  • 1
  • 30
  • 37
6

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}`,
});
                  
Sangeet Agarwal
  • 1,674
  • 16
  • 25
6

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}) }} 
soma iyappan
  • 482
  • 7
  • 16
5

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

Zukron Alviandy
  • 106
  • 2
  • 3
  • amazingly concise answer. With React Router v5, you can simply uselocation() hook ```const location = useLocation() const data = location.state ``` – Amir Apr 18 '21 at 15:59
3

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.

joedotnot
  • 4,810
  • 8
  • 59
  • 91
  • I think you didn't need `withRouter` because you wrapped your component with `BrowserRouter`, which works the same. – Pandemonium Dec 04 '18 at 18:08
  • Yes and you are passing the `props` down into each component which include the `history` prop. – Jeremy May 18 '20 at 09:46
2

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

P Mill
  • 31
  • 1
-10

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

kamal pandey
  • 147
  • 1
  • 4