Passing optional parameter in react router - javascript

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

Related

this.props.match.params.id in React.js is undefined

I want to get the id from the URL therefore I can use this id to get and output the user info but I can't get id from URL. I've seen useParams() but I think it is not applicable with class component. May I know if there is an alternative solution for this?
async componentDidMount(){
const stud_id = this.props.match.params.id;
console.log(stud_id);
}
see error message from console here
The most common way of reading URL params in React is using React Router. In React Router, you get URL params with this.props.match.params like you are trying to, but you have to call your component inside a Route, like for example:
<Route
path="/:id"
component={YourComponent}
/>
instead of just
<YourComponent />
So that your component receives the match prop and can access this.props.match.params.id
If you're using
<Route path="/blah" component={()=><YourComponent someProp={someProp}>}/>
I mean, with arrow function as it child component, you have to pass the pros of the father (Route) to the child (YourComponent) like that:
<Route path="/blah" component={({match})=><YourComponent match={match} someProp={someProp}>}/>
Because you're creating a new "generation" so you have to pass the props by your self

how to check if url param entered exist in location.pathname via React

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'} />

Unable to access Query String parameters inside a React Component

Here's what I have done so far,
This is the Route that I have defined for a page
<Route path='emails/user/view/:id' component={AccountEmails} />
And here's where the Component is being rendered
const AccountEmails = ({params: {id}}) => <ReceiptsListBox url={"/api/accounts/"+id+"/receipts.json"}></ReceiptsListBox>
Now, within the render() method of the component, I tried to console.log(this.props.location.query) unfortunately this.props.location is undefined.
Here's the YouTube video that I have referred to.
react-router version 2.8.1 and react version 15.3.2
Use this:
const AccountEmails = props => {
const {id} = props.params;
return <ReceiptsListBox
url={"/api/accounts/"+id+"/receipts.json"}
{...props} // =====> notice this part, important
</ReceiptsListBox>
}
Reason is: You are passing only url in props, not all the props values that AccountEmails receives from Routes, because of that location is not available inside ReceiptsListBox component.
Solution is pass all the props that AccountEmails component receive along with one extra url value, by that way location will be available inside ReceiptsListBox component.

Get path params in react-router v4

I'm trying to build a router link through my application,
In this scenario, I have three files.
App.js
Book.js
DetailedView.js
I have inside of Book built up a <Link> that only appears when hovered ( over a book cover )
{this.state.isHovered ? (
<Link to={`/details/${this.props.book.industryIdentifiers[1].identifier}`}>
<div className="hover-box"></div>
</Link>) : ( <div /> )}
This will take me to a /details/12345 (isbn10 number)
The thing I have a hard time to understand is how to for example
setState({iPressedThisBook}) when pressing <Link> or if i can use the part after /12345 to create like a filter
Because in App the Route will be hooked up as...
<Route path="/details/:id" render={() => (
<BookDetailedView
bookStateUpdated = {this.bookStateUpdated}
book = {this.state.books}
/>
)}/>
I, later on, want to grab the :id so that I make for example a this.props.book.find(:id) inside of my <BookDetailedView>
In order to receive the path param in you component, you need to first connect your component with withRouter HOC from react-router so that you can access the Router props and get the path params from the match props as this.props.match.params.id
Sample Code:
import {withRouter} from 'react-router';
class BookDetailedView extends React.Component {
render() {
var id = this.props.match.params.id
}
}
export default withRouter(BookDetailedView) ;
or simply passing it with render prop in route as
<Route path="/details/:id" render={({match}) => (
<BookDetailedView
bookStateUpdated = {this.bookStateUpdated}
book = {this.state.books}
id={match.params.id}
/>
)}/>
From the React Documentation of match
match
A match object contains information about how a <Route path> matched
the URL. match objects contain the following properties:
params - (object) Key/value pairs parsed from the URL corresponding to the dynamic segments of the path
isExact - (boolean) true if the entire URL was matched (no trailing characters)
path - (string) The path pattern used to match. Useful for building nested s
url - (string) The matched portion of the URL. Useful for building nested s
You’ll have access match objects in various places:
Route component as this.props.match
Route render as ({ match }) => ()
Route children as ({ match }) => ()
withRouter as this.props.match
matchPath as the return value
If a Route does not have a path, and therefore always matches, you’ll
get the closest parent match. Same goes for withRouter
You can access :id by doing
this.props.params.id
you can handle routing many ways, you don't have to do a
you can also handle it in a function .
function doSomethingWhenClicked(id)
{
doSomething();
this.props.history.push({
pathname: '/example/'+id
});
}
and bind this function on a onclick element

Route matching in React

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?

Categories