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');
});
Route
should have access to this.props.location
, this.props.history
, etc. I think you don't need to use ref
anymore with v4. Try doing this.props.history.push('/template');
props
to the component that matches the route? I think this GitHub thread addresses your concern.
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
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]);
};
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 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:
on the history.push component: this.props.history.push(`/home:${this.state.userID}`) on the router component you define the route:
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>
);
}
useLocation<IState>()
so you don't have to assert in the next line
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}`,
});
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
const location = useLocation() const data = location.state
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}) }}
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.
withRouter
because you wrapped your component with BrowserRouter
, which works the same.
props
down into each component which include the history
prop.
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
Success story sharing
this.props.history.push('/template',response.data)
not working. According to docs ofpush(path, [state])
, don't you think it should work?