75

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,713
  • 3
  • 16
  • 34

6 Answers6

118

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,362
  • 2
  • 23
  • 37
Sakhi Mansoor
  • 7,832
  • 5
  • 22
  • 37
  • 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
  • 3
    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
  • 1
    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
61

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
  • 626
  • 6
  • 2
  • 4
    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
  • 1
    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
  • 1
    @sammms not the author, but I believe they just meant in the Redirect Component. You can add this to any Redirect Component that you wish to pass props with, provided the Route component has a render prop set as a function. [See here for more about Redirect to](https://reactrouter.com/web/api/Redirect/to-object), and [here for more about Route render](https://reactrouter.com/web/api/Route/render-func) – Mxt Jun 12 '21 at 19:20
  • When I ran this code, it resulted in a blank page when I was returning `Redirect` – Saiansh Singh Jun 21 '21 at 17:53
  • What if the rendered component is a function and not a class? – Suncat2000 May 12 '22 at 21:15
18

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,622
  • 5
  • 39
  • 71
5

With Functional Components/Hooks, react-router-dom version 5.2.0 and passing down both Function and regular props:

Using @Barat Kumar answer, here you can also see how to pass and access functions as props with Redirect. Note that there is also a difference in how you access the property_id prop.

The Route is the same:

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

The Redirect:

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

Accessing both props inside NewTestComp:

 useEffect(() => {
   console.log(props.history.location.testFunc);
   console.log(props.history.location.state.property_id);          
 }, []);

Note that "state" came from the use in Class Components. Here you can use any name you want and also pass regular props just like we did the function. So, departing a bit more from @Barat Kumar accepted answer, you can:

<Redirect
  to={{
    pathname: "/test/new",
    testFunc: testFunc,
    propetries: { property_id: property_id1, property_id2: property_id2},
    another_prop: "another_prop"
  }}
/>

And access those like so:

console.log(props.history.location.testFunc);
console.log(props.history.location.propetries.property_id1);
console.log(props.history.location.propetries.property_id2);
console.log(props.history.location.another_prop);
danrivative
  • 181
  • 2
  • 5
1
  • 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 useRedirectToLocation = (params="1") => {
if(params){
withRefresh.push({
    pathname: `${ROOT_PATH}/create`,
    state: { id: `${params}` }
  });
}
} 

export default  useRedirectToLocation;

  • and use it like :

 import useRedirectToLocation from  './useRedirectToLocation


const handleOnClick = params => useRedirectToAccounting(params)

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

** this can be further refactored based on requirement.

Ashif Zafar
  • 623
  • 5
  • 6
1
<Redirect to={{
    pathname: '/path',
    state: { id: '123' }
}} />

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

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81