I am using react with react-router.
I am trying to pass property’s in a “Link” of react-router
var React = require('react'); var Router = require('react-router'); var CreateIdeaView = require('./components/createIdeaView.jsx'); var Link = Router.Link; var Route = Router.Route; var DefaultRoute = Router.DefaultRoute; var RouteHandler = Router.RouteHandler; var App = React.createClass({ render : function(){ return( <div> <Link to="ideas" params={{ testvalue: "hello" }}>Create Idea</Link> <RouteHandler/> </div> ); } }); var routes = ( <Route name="app" path="/" handler={App}> <Route name="ideas" handler={CreateIdeaView} /> <DefaultRoute handler={Home} /> </Route> ); Router.run(routes, function(Handler) { React.render(<Handler />, document.getElementById('main')) });
The “Link” renders the page but does not pass the property to the new view.
Below is the view code
var React = require('react'); var Router = require('react-router'); var CreateIdeaView = React.createClass({ render : function(){ console.log('props form link',this.props,this)//props not recived return( <div> <h1>Create Post: </h1> <input type='text' ref='newIdeaTitle' placeholder='title'></input> <input type='text' ref='newIdeaBody' placeholder='body'></input> </div> ); } }); module.exports = CreateIdeaView;
How can I pass data using “Link”?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This line is missing path
:
<Route name="ideas" handler={CreateIdeaView} />
Should be:
<Route name="ideas" path="/:testvalue" handler={CreateIdeaView} />
Given the following Link
(outdated v1):
<Link to="ideas" params={{ testvalue: "hello" }}>Create Idea</Link>
Up to date as of v4/v5:
const backUrl = '/some/other/value' // this.props.testvalue === "hello" // Using query <Link to={{pathname: `/${this.props.testvalue}`, query: {backUrl}}} /> // Using search <Link to={{pathname: `/${this.props.testvalue}`, search: `?backUrl=${backUrl}`} /> <Link to={`/${this.props.testvalue}?backUrl=${backUrl}`} />
and in the , out dated usage of withRouter(CreateIdeaView)
components render()
withRouter
higher order component:
console.log(this.props.match.params.testvalue, this.props.location.query.backurl) // output hello /some/other/value
And in a functional components using the useParams
and useLocation
hooks:
const CreatedIdeaView = () => { const { testvalue } = useParams(); const { query, search } = useLocation(); console.log(testvalue, query.backUrl, new URLSearchParams(search).get('backUrl')) return <span>{testvalue} {backurl}</span> }
From the link that you posted on the docs, towards the bottom of the page:
Given a route like
<Route name="user" path="/users/:userId"/>
Updated code example with some stubbed query examples:
// import React, {Component, Props, ReactDOM} from 'react';
// import {Route, Switch} from 'react-router'; etc etc
// this snippet has it all attached to window since its in browser
const {
BrowserRouter,
Switch,
Route,
Link,
NavLink
} = ReactRouterDOM;
class World extends React.Component {
constructor(props) {
super(props);
console.dir(props);
this.state = {
fromIdeas: props.match.params.WORLD || 'unknown'
}
}
render() {
const { match, location} = this.props;
return (
<React.Fragment>
<h2>{this.state.fromIdeas}</h2>
<span>thing:
{location.query
&& location.query.thing}
</span><br/>
<span>another1:
{location.query
&& location.query.another1
|| 'none for 2 or 3'}
</span>
</React.Fragment>
);
}
}
class Ideas extends React.Component {
constructor(props) {
super(props);
console.dir(props);
this.state = {
fromAppItem: props.location.item,
fromAppId: props.location.id,
nextPage: 'world1',
showWorld2: false
}
}
render() {
return (
<React.Fragment>
<li>item: {this.state.fromAppItem.okay}</li>
<li>id: {this.state.fromAppId}</li>
<li>
<Link
to={{
pathname: `/hello/${this.state.nextPage}`,
query:{thing: 'asdf', another1: 'stuff'}
}}>
Home 1
</Link>
</li>
<li>
<button
onClick={() => this.setState({
nextPage: 'world2',
showWorld2: true})}>
switch 2
</button>
</li>
{this.state.showWorld2
&&
<li>
<Link
to={{
pathname: `/hello/${this.state.nextPage}`,
query:{thing: 'fdsa'}}} >
Home 2
</Link>
</li>
}
<NavLink to="/hello">Home 3</NavLink>
</React.Fragment>
);
}
}
class App extends React.Component {
render() {
return (
<React.Fragment>
<Link to={{
pathname:'/ideas/:id',
id: 222,
item: {
okay: 123
}}}>Ideas</Link>
<Switch>
<Route exact path='/ideas/:id/' component={Ideas}/>
<Route path='/hello/:WORLD?/:thing?' component={World}/>
</Switch>
</React.Fragment>
);
}
}
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('ideas'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.3.1/react-router.min.js"></script>
<div id="ideas"></div>
#updates:
From the upgrade guide from 1.x to 2.x:
<Link to>
, onEnter, and isActive use location descriptors
<Link to>
can now take a location descriptor in addition to strings.
The query and state props are deprecated.// v1.0.x
<Link to="/foo" query={{ the: 'query' }}/>// v2.0.0
<Link to={{ pathname: '/foo', query: { the: 'query' } }}/>// Still valid in 2.x
<Link to="/foo"/>Likewise, redirecting from an onEnter hook now also uses a location
descriptor.// v1.0.x
(nextState, replaceState) => replaceState(null, '/foo') (nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })// v2.0.0
(nextState, replace) => replace('/foo') (nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })For custom link-like components, the same applies for router.isActive,
previously history.isActive.// v1.0.x
history.isActive(pathname, query, indexOnly)// v2.0.0
router.isActive({ pathname, query }, indexOnly)
#updates for v3 to v4:
- https://github.com/ReactTraining/react-router/blob/432dc9cf2344c772ab9f6379998aa7d74c1d43de/packages/react-router/docs/guides/migrating.md
- https://github.com/ReactTraining/react-router/pull/3803
- https://github.com/ReactTraining/react-router/pull/3669
- https://github.com/ReactTraining/react-router/pull/3430
- https://github.com/ReactTraining/react-router/pull/3443
- https://github.com/ReactTraining/react-router/pull/3803
- https://github.com/ReactTraining/react-router/pull/3636
- https://github.com/ReactTraining/react-router/pull/3397
- https://github.com/ReactTraining/react-router/pull/3288
The interface is basically still the same as v2, best to look at the CHANGES.md for react-router, as that is where the updates are.
“legacy migration documentation” for posterity
- https://github.com/ReactTraining/react-router/blob/dc7facf205f9ee43cebea9fab710dce036d04f04/packages/react-router/docs/guides/migrating.md
- https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v1.0.0.md
- https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v2.0.0.md
- https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v2.2.0.md
- https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v2.4.0.md
- https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v2.5.0.md
Method 2
there is a way you can pass more than one parameter. You can pass “to” as object instead of string.
// your route setup <Route path="/category/:catId" component={Category} / > // your link creation const newTo = { pathname: "/category/595212758daa6810cbba4104", param1: "Par1" }; // link to the "location" // see (https://reacttraining.com/react-router/web/api/location) <Link to={newTo}> </Link> // In your Category Component, you can access the data like this this.props.match.params.catId // this is 595212758daa6810cbba4104 this.props.location.param1 // this is Par1
Method 3
I had the same problem to show an user detail from my application.
You can do this:
<Link to={'/ideas/'+this.props.testvalue }>Create Idea</Link>
or
<Link to="ideas/hello">Create Idea</Link>
and
<Route name="ideas/:value" handler={CreateIdeaView} />
to get this via this.props.match.params.value
at your CreateIdeaView class.
You can see this video that helped me a lot: https://www.youtube.com/watch?v=ZBxMljq9GSE
Method 4
The simple is that:
<Link to={{ pathname: `your/location`, state: {send anything from here} }}
Now you want to access it:
this.props.location.state
Method 5
as for react-router-dom 4.x.x (https://www.npmjs.com/package/react-router-dom) you can pass params to the component to route to via:
<Route path="/ideas/:value" component ={CreateIdeaView} />
linking via (considering testValue prop is passed to the corresponding component (e.g. the above App component) rendering the link)
<Link to={`/ideas/${ this.props.testValue }`}>Create Idea</Link>
passing props to your component constructor the value param will be available via
props.match.params.value
Method 6
After install react-router-dom
<Link to={{ pathname: "/product-detail", productdetailProps: { productdetail: "I M passed From Props" } }}> Click To Pass Props </Link>
and other end where the route is redirected do this
componentDidMount() { console.log("product props is", this.props.location.productdetailProps); }
Method 7
Typescript
For approach mentioned like this in many answers,
<Link to={{ pathname: "/my-path", myProps: { hello: "Hello World" } }}> Press Me </Link>
I was getting error,
Object literal may only specify known properties, and ‘myProps’ does not exist in type ‘LocationDescriptorObject | ((location: Location) => LocationDescriptor)’
Then I checked in the official documentation they have provided state
for the same purpose.
So it worked like this,
<Link to={{ pathname: "/my-path", state: { hello: "Hello World" } }}> Press Me </Link>
And in your next component you can get this value as following,
componentDidMount() { console.log("received "+this.props.location.state.hello); }
Method 8
To work off the answer above (https://stackoverflow.com/a/44860918/2011818), you can also send the objects inline the “To” inside the Link object.
<Route path="/foo/:fooId" component={foo} / > <Link to={{pathname:/foo/newb, sampleParam: "Hello", sampleParam2: "World!" }}> CLICK HERE </Link> this.props.match.params.fooId //newb this.props.location.sampleParam //"Hello" this.props.location.sampleParam2 //"World!"
Method 9
For v5
<Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true } }} />
Method 10
Inside your Link component do the state
<Link to='register' state={{name:'zayne'}}>
Now to access the item in the page you went to, import useLocation
import {useLocation} from 'react-router-dom'; const Register=()=>{ const location = useLocation() //store the state in a variable if you want //location.state then the property or object you want const Name = location.state.name return( <div> hello my name is {Name} </div> ) }
Method 11
In my case I had a function component with empty props and this solved it:
<Link to={{ pathname: `/dashboard/${device.device_id}`, state: { device }, }} > View Dashboard </Link>
In your function component you should have something like this:
import { useLocation } from "react-router" export default function Dashboard() { const location = useLocation() console.log(location.state) return <h1>{`Hello, I'm device ${location.state.device.device_id}!`}</h1> }
Method 12
The simplest approach would be to make use of the to:object
within link
as mentioned in documentation:
https://reactrouter.com/web/api/Link/to-object
<Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true, id: 1 } }} />
We can retrieve above params (state) as below:
this.props.location.state // { fromDashboard: true ,id: 1 }
Method 13
If you are just looking to replace the slugs in your routes, you can use generatePath
that was introduced in react-router 4.3 (2018). As of today, it isn’t included in the react-router-dom (web) documentation, but is in react-router (core). Issue#7679
// myRoutes.js export const ROUTES = { userDetails: "/user/:id", } // MyRouter.jsx import ROUTES from './routes' <Route path={ROUTES.userDetails} ... /> // MyComponent.jsx import { generatePath } from 'react-router-dom' import ROUTES from './routes' <Link to={generatePath(ROUTES.userDetails, { id: 1 })}>ClickyClick</Link>
It’s the same concept that django.urls.reverse
has had for a while.
Method 14
I was struggling with this for a few hours and not a single answer in this topic worked for me. Finally I managed to find a solution for React Router 6 in the documentation.
Here is full example:
// App.js <BrowserRouter> <Routes> <Route path="/books/:bookId" element={ <BookDetails /> } /> </Routes> </BrowserRouter>
// BookDetails.js import React from "react" import { useParams } from "react-router-dom" export default function BookPage() { const params = useParams() return <div> { console.log(params.bookId) } </div> }
Note that useParams
cannot be called inside a class component so you must use function component (see this answer for details).
Method 15
Route:
<Route state={this.state} exact path="/customers/:id" render={(props) => <PageCustomer {...props} state={this.state} />} />
And then can access params in your PageCustomer component like this: this.props.match.params.id
.
For example an api call in PageCustomer component:
axios({ method: 'get', url: '/api/customers/' + this.props.match.params.id, data: {}, headers: {'X-Requested-With': 'XMLHttpRequest'} })
Method 16
Updating 25-11-21
Thanks for alex-adestech.mx who wrote above.
I was able to transfer the whole object and pull out all the necessary fields from it
in send-component :
<Button type="submit" component={NavLink} to={{ pathname: '/basequestion', state: {question} }} variant="contained" size="small">Take test</Button>
in receive-component:
import { useLocation } from "react-router" const BaseQuestion = () => { const location = useLocation(); const {description, title, images} = (location.state.question);
Method 17
For v6:
// route setup <Route path="/employee-edit/:empId" element={<EmployeeEdit />} / >
Link
to Component
<Link to={"/employee-edit/1"} state={{ data: employee }} > Edit </Link>
or
<Link to={{ pathname: "/employee-edit/1", search: "?sort=name", hash: "#the-hash", }} state={{ data: employee }} > Edit </Link>
Note: state
is outside from to{}
, but for
v5:
<Link to={{ pathname: "/courses", search: "?sort=name", hash: "#the-hash", state: { fromDashboard: true } }} />
Funtional component:
import React from "react"; import { useLocation } from "react-router-dom"; const LinkTest = () => { const location = useLocation(); console.log("Location", location); return <h1>Link Test</h1>; }; export default LinkTest;
Class Component: in order to work with hooks, we need to wrap it in functional component and pass props:
import React, { Component } from "react"; import { useLocation, useParams } from "react-router-dom"; class LinkTestComponent extends Component { render() { console.log(this.props); return <h1>Link Test</h1>; } } export default () => ( <LinkTestComponent params={useParams()} location={useLocation()} /> );
Tested with: "react-router-dom": "^6.2.2",
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0