63

How should you pass props with the Redirect component without having them exposed in the url?

Like this <Redirect to="/order?id=123 />"? I'm using react-router-dom.

Michiel
  • 1,131
  • 1
  • 11
  • 23

5 Answers5

104

You can pass data with Redirect like this:

<Redirect to={{
            pathname: '/order',
            state: { id: '123' }
        }}
/>

and this is how you can access it:

this.props.location.state.id

The API docs explain how to pass state and other variables in Redirect / History prop.

Source: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Redirect.md#to-object

user2954463
  • 2,116
  • 1
  • 20
  • 35
Sakhi Mansoor
  • 6,103
  • 4
  • 17
  • 31
  • Do I need the `BrowserHistory` component to get this working? – Michiel Aug 28 '18 at 18:39
  • No you don't. As long as you're using any router in your routes. – Sakhi Mansoor Aug 28 '18 at 18:43
  • Awesome thanks, I'll mark your response as the solution as soon at the timer expired! :) – Michiel Aug 28 '18 at 18:44
  • This solution doesn't follow the html 5 browser history specification, data should be passed in a state object. – Anas Aug 28 '18 at 18:44
  • @anas this is what the library author recommends: https://github.com/ReactTraining/history#navigation – Sakhi Mansoor Aug 28 '18 at 18:49
  • @SakhiMansoor the url you provided says that you should `npm install history`? What if I don't have that done, or is it already in the `react-router-dom` package? – Michiel Aug 28 '18 at 18:53
  • 1
    @SakhiMansoor Yes the object should contain `pathname`, `search`, `state`, etc which are values used by the browser history. Any custom values should be included in the `state` object which is one level down. It's cleaner and separates what's used by the browser history from your own custom object. – Anas Aug 28 '18 at 18:53
  • 2
    Thank you @Anas and SakhiMansoor for the help. You guys both deserve the solution mark ! :) – Michiel Aug 28 '18 at 18:56
  • Yes I agreed @Anas but I'm more interested any particular reason behind this ? – Sakhi Mansoor Aug 28 '18 at 19:02
  • One reason would be, let's say in the next release they add `id` to their api, now you have a conflict. – Anas Aug 28 '18 at 19:08
  • That’s one of the concern. But we should read migration docs before updating packages and yes I would edit my answer. Btw thanks it’s a learning for me as well. – Sakhi Mansoor Aug 28 '18 at 19:17
  • 1
    @SakhiMansoor I tried the same code but it gives me this error: Object literal may only specify known properties, and 'id' does not exist in type 'LocationDescriptor'. – Mustafa Chelik Oct 27 '18 at 14:51
  • please share your code or post a new question specifying your problem. Thanks – Sakhi Mansoor Oct 27 '18 at 14:53
  • @SakhiMansoor ; Thank you very much – Mustafa Chelik Oct 27 '18 at 14:53
  • 1
    This works apparently ; – Mustafa Chelik Oct 27 '18 at 14:55
  • Updating my answer since React-router has brought changes in their API. thanks for pointing this out. State is perfect way to store values as they don't collide with keys given in API like pathname etc – Sakhi Mansoor Oct 27 '18 at 14:58
  • 2
    Hi... I am having a bit trouble receiving the state param passed with redirect. this.props.location gives me undefined. Any suggestions? – Dhruv Singhal Jan 03 '19 at 13:37
  • This worked for me but in my case I needed to use `mydata: JSON.stringify(data)` and `JSON.parse(props.location.state.mydata)` because I was passing an object. – Michael Lynch Aug 06 '19 at 20:41
  • @DhruvSinghal Same issue here. Did you find a solution? – Sealer_05 Oct 11 '19 at 19:15
  • @Sealer_05 I stopped working on React a while ago... Don't clearly remember how I solved this. Try experimenting a bit to find out. – Dhruv Singhal Oct 14 '19 at 10:38
  • I am getting this.props as undefined. Any ideas why is it so? – vipulsinghthakur Feb 27 '20 at 20:17
  • can you share codesandbox or github link I could look into it – Sakhi Mansoor Feb 27 '20 at 23:36
  • If the component you're redirecting to is a functional component, use React Router's `useLocation` hook to access the location object. – Thibaut May 03 '20 at 07:36
  • @SakhiMansoor currently flagged another answer as correct. Could you update your content to the one that's currently flagged? The currently flagged one could be better explained, have a try :) – Michiel Aug 27 '20 at 07:04
34

You should first pass the props in Route where you have define in your App.js

<Route path="/test/new" render={(props) => <NewTestComp {...props}/>}/>

then in your first Component

<Redirect
            to={{
            pathname: "/test/new",
            state: { property_id: property_id }
          }}
        />

and then in your Redirected NewTestComp you can use it where ever you want like this

componentDidMount(props){
console.log("property_id",this.props.location.state.property_id);}
Barat Kumar
  • 356
  • 3
  • 2
  • 2
    Underrated answer- this is a full solution; simply adding the line in the above answers doesn't properly pass the props. – bearacuda13 May 29 '20 at 20:22
  • This is the CRUCIAL part. Simple and very helpful to say the least! – sonic98 Aug 20 '20 at 10:59
  • Flagged as new correct answer since this one has more information. – Michiel Aug 27 '20 at 07:00
  • can you elaborate on 'then in your first Component'? I'm having trouble fitting this all together. which component is the 'first component'? – sammms Apr 27 '21 at 15:17
17

You can use browser history state like this:

<Redirect to={{
    pathname: '/order',
    state: { id: '123' }
}} />

Then you can access it via this.props.location.state.id

Source: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Redirect.md#to-object

Anas
  • 5,267
  • 5
  • 38
  • 67
1
<Redirect to={{
    pathname: '/path',
    state: { id: '123' }
}} />

Then you can access it via this.props.location.state.id in the desired component

Codemaker
  • 4,115
  • 1
  • 32
  • 30
0
  • You can come with your own hook for the same purpose :
import { createBrowserHistory } from "history";

const withRefresh = createBrowserHistory({ forceRefresh: true });
const ROOT_PATH = process.env.PUBLIC_URL || "/myapp";

const useRedirectToAccounting = (params="1") => {
if(params){
withRefresh.push({
    pathname: `${ROOT_PATH}/create`,
    state: { id: `${params}` }
  });
}
} 

export default  redirectToAccounting;

  • and use it like :

 import useRedirectToAccounting from  './redirectToAccounting


const handleOnClick = params => useRedirectToAccounting(params)

const RedirectorComponent = () => <a onClick={handleOnClick}>{"Label"}</a>

** this can be further refactored based on requirement.

Ashif Zafar
  • 373
  • 2
  • 5