I want to make a page with url users/:userId where userId will be (java, cpp, c).So in home page if click on java button it will open a page wit url users/java, similarly for c and cpp.All these pages will have same layout with different data.For this I made a simple component as Lang.jsx
export class Lang extends Component{
render() {
const { data } = this.props;
return (
<div>
<h1>{data.lang}</h1>
</div>);
}
}
In Router class we have to write something as
<Route path="users/:userId" component={Lang} />
But it is not clear how to pass userId in router and
load Lang for each url?
Use Link for these java, cpp, c, like this:
<Link to='users/java'>Java</Link>
<Link to='users/cpp'>Cpp</Link>
<Link to='users/c'>C</Link>
If you are using history.push() then write it like this:
hashHistory.push('users/java');
Note: You can make that userid optional because if you don't pass userid it will not match to any route, write it like this to make it optional:
<Route path="users/(:userId)" component={Lang} />
Now if you don't pass anything then also it will open the Lang page.
One more thing since you are passing the parameter by name userId, so it will available by this.props.params.userId not by this.props.data.lang.
I'm not completely sure what you're trying to do here, but if you have a look at this.props inside of lang, there will be a params key (this.props.params), which will be an object containing the userId.
eg:
this.props = {
params: {
userId: '1234',
},
}
This means that when you go to /user/1234, the userId key will have the value of 1234.
I'm not really sure what you're expecting the value of data.lang to be. Are you wrapping the routes in another route that provides that prop? What library are you using for lang?
Related
I have setup gatsby project using this link. It is working correctly.
Now I know how to create route by defining the component inside the pages folder. But now I have a new challenge I need to create one dynamic route so that I can pass my id in it (Just like reactjs).
<Route path: "/path/:id"/>
How do I do that in gatsby?
You have to explicitly tell gatsby that a path should be dynamic. From the docs:
// gatsby-node.js
// Implement the Gatsby API “onCreatePage”. This is
// called after every page is created.
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
page.matchPath = "/app/*"
// Update the page.
createPage(page)
}
}
and then you can use dynamic routing in src/pages/app.js
import { Router } from "#reach/router"
const SomeSubPage = props => {
return <div>Hi from SubPage with id: {props.id}</div>
}
const App = () => (
<Layout>
<Link to="/app/1">First item</Link>{" "}
<Link to="/app/2">Second item</Link>{" "}
<Router>
// ...dynamic routes here
<SomeSubPage path="/app/:id" />
</Router>
</Layout>
)
export default App
Everything that goes to /app/* will be handled dynamically now. You should find your id as usual in the props.
Have a look at their authentication example https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth
You can use square brackets ([ ]) in the file path to mark any dynamic segments of the URL. For example, in order to edit a user, you might want a route like /user/:id to fetch the data for whatever id is passed into the URL.
src/pages/users/[id].js will generate a route like /users/:id
src/pages/users/[id]/group/[groupId].js will generate a route like /users/:id/group/:groupId
Reference: https://www.gatsbyjs.com/docs/reference/routing/file-system-route-api#creating-client-only-routes
You can use gatsby-plugin-create-client-paths. It uses matchPath. For more info check
https://www.gatsbyjs.org/docs/gatsby-internals-terminology/#matchpath
https://www.gatsbyjs.org/packages/gatsby-plugin-create-client-paths/
This answer is Super late, but for anyone in the future who is faced with this problem, I have a simpler solution.
In Gatsby terms it's called a Splat Route.
For examples, If you want some page "domain.com/profile/[id]", where id can be any number, which will be used to display different data inside the website, you should name your page as [...id].
Now inside the page you can access this id as
const ProfilePage = (props) => <div>This page is for id number {props.params.id}</div>
Note: Don't miss the 3 dots, that is what signifies a splat route in gatsby.
Well, I try to understand legacy code with React routes onboard.
I have an url like
/home/reports/some_report_numbers
when user changes the ulr like that:
/home/reports/some_report_numb
I want to check if "some_report_numb" exists in props, in this.props.location.pathname. If exists - fine, go that way, otherwise go another way.
Maybe it is a wrong approach at all? Well, when the report is shown and user just deletes some letters in url I need to redirect to /home/ page. To do that I need somehow to check if that report with that numbers exists at all.
Maybe it could be done via
<Route name={SomeRouteName} path='reports/:reportId' component={HomePage} />
According to the documentation of react-router-dom
Link: https://reacttraining.com/react-router/web/example/url-params
match become an object that can be used in your component. Like explain in the documentation, you have access to match object with the following steps:
Route component as this.props.match
Route render as ({ match }) => ()
Route children as ({ match }) => ()
withRouter as this.props.match
matchPath as the return value
For example, if you have the following route:
<Route path="/reports/:reportId" component={HomePage} />
In your component, you can access to this with: this.props.match because it's an object and inside it, you will have what you want.
After that, you could check what params you have in your URL.
Now, if you want to redirect the user, you can use <Redirect to={'/your/path'} />
Say I have http://www.example.com/page/#/search routed like this:
<Router history={hashHistory}>
<Route path='/search/' component={SearchPage} />
</Router>
And when the user does a search on the page using the provided name and age search boxes (either can be left out, or both can be filled), I want it to redirect to:
http://www.example.com/page/#/search/?name=whatever%20name&age=15
Which will display the results for this particular search. This would also allow linking directly to search results.
Now inside my SearchPage component, how can I check if ?name= or ?age= or any other search parameters have been provided?
In your container say SearchPage you can access queryParams like this
this.props.location.query.yourKey.
As an example
class SearchPage extends React.Component{
componentWillMount(){
const {name, age} = this.props.location.query;
//here you can give default values if they are empty
//do whatever you want
}
}
There are two ways of achieving this either you can use params or query values.
By params:
In the route first define your optional parameters like this:
<Router history={hashHistory}>
<Route path='/search(/:name)(/:age)' component={SearchPage} />
</Router>
Include componentWillReceiveProps() method in your component it will get triggered whenever component receive any new props, like this:
componentWillReceiveProps(newProps){
console.log(newProps.params.name, newProps.params.age);
// here you can check the props value
}
In the component you can check the value by this.props.params.name or age.
By query parameter:
no change is required in the route, just pass the values in url and check like this:
this.props.location.name or age.
Read this article for about params and query values in react: https://www.themarketingtechnologist.co/react-router-an-introduction/
With the latest update "location.query" is not exposed, we have to use "location.search" to get the optional unnamed parameters. However, The named optional parameter still can be read through "props.match.params"
Route :
<Route path="/partner/list-space/step-1/:_id?" component={ListSpace}/>
Fetching the named optional parameter "id" in component or hooks
let id = props.match.params._id;
To fetch the unnamed optional parameter such as "space" from the url.
http://localhost:3000/partner/list-space/step-1/123?space=new&guests=4
We have to use "querystringify".
import qs from "querystringify";
const qsParams = qs.parse(props.location.search);
Results :
props.match.params._id => "123"
qsParams.space => new
qsParams.guests => 4
How do I get the params of a route inside a react component
Im using react containers from the react composer package
if this is the whole route
https://learnbuildrepeat-tevinthuku.c9users.io/ReadProjectMeta/wD98XTTtpf8ceyRJT
How do I get only
wD98XTTtpf8ceyRJT
and store its value in a variable inside a react component.
Ive tried to use
FlowRouter.getParam() but it doesnt work. I keep getting undefined
import React from 'react';
export default class ReadProjectMetaLayout extends React.Component {
render() {
var category = FlowRouter.getQueryParam();
console.log(category);
return (
<div>
<h4>Hello World</h4>
</div>
)
}
}
this is the route
FlowRouter.route("/ReadProjectMeta/:_id", {
name: 'project.meta',
action(params) {
mount(ReadProjectMetaLayoutContainer, {
components: (<ReadProjectMeta _id={params._id}/>)
})
}
});
What could be the problem and how do I solve it
To only get the last part of the string:
location.pathname.substr((location.pathname.lastIndexOf('/')+1))
Another pure meteor based thing you can try is from this reference:
FlowRouter.getParam(":_id");
NOTE: Your solution didn't work as you are getting query parameter, query parameters are the parameters that are passed in the url after '?'
i.e. /apps/this-is-my-app?show=yes&color=red
Here in above code color and show are query parameters, while apps is a part of pathname
FlowRouter.getParam(paramName) returns the value of a single URL
parameter
FlowRouter.getQueryParam(paramName) returns the value of a single URL query parameter
Reference:
https://guide.meteor.com/routing.html#accessing-route-info
Im using React Router to navigate to a page in my app like this:
<Link to={`/single/${this.props.data.pageId}`} params={{singleId: 1}}>GotoPage!</Link>
This works fine but I would also like to pass an additional property to the new page.
When rendering a component without using Link I would do something like:
<MyComponent myProp={this.props.data}/>
I have tried passing myProp={this.props.data} along in params like this:
<Link to={`/single/${this.props.data.pageId}`} params={{singleId: 1, myProp={this.props.data}}}>GotoPage!</Link>
But it does not seem to work as myProp is undefined on the new page as oppose to pageId which I can get like:
this.props.params.pageId;
Am I not supposed to be able to pass non-route related parameters with Link?
In the documentation for Link and also the source, there's no mention of it taking param. But I get what you're trying to do.
Instead of hard-coding routes, may I recommend using react-router's history function router.push(). Do something like this instead:
class Foo extends React.Component {
...
const handleNewRoute = () => {
let { pageId } = this.props.data
let singleId = '1'
this.context.router.push({ // use push
pathname: `/single/${pageId}`,
query: { singleId }
})
}
render() {
return (
<button onLeftClick={this.handleNewRoute} />
)
}
}
By the way, in React/JSX, something like ...{{singleId: 1, myProp={this.props.data}}}... should be <Link...foobar={{singleId: 1, myProp: this.props.data}}>. The former syntax is wrong.
I think the better way to get the additional data is an ajax.
But if you want your way to do this,I check the api of Link and I find a query property.
query:
An object of key:value pairs to be stringified.
so you can use this to pass a object of key:value to the next route,but this object will be stringified and passed though the url I think.I prefer an ajax for this.