Reputation: 2750
I am new to React and trying to render a page based on the name query like http://localhost:3000/show?name=james
So I initially added the Route as :
<BrowserRouter>
<Switch>
<Route path='*' component={ErrorComponent} />} />
<Route path="show(/:name)" name="name" component={Show}></Route>
</Switch>
</BrowserRouter>
And then I tried to render the component Show like below:
import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
componentDidMount(){
console.log(this.props.location.search);
const values = queryString.parse(this.props.location.search);
console.log(values.name);
}
render() {
const { params } = this.props.match;
return <div>
<h4>About</h4>
<p>This is About page.</p>
{params.id ? <b>ID: {params.id}</b> : <i>ID is optional.</i>}
</div>
}
}
export default Show;
then when I try to show the page
http://localhost:3000/show?name=james
It always show 404. Not sure which part I am doing it wrong. Any help is appreciated. Also I am using react-router-dom 5.1.2 . Thanks.
Upvotes: 0
Views: 2840
Reputation: 11027
EDIT: Can't believe I didn't notice this originally...
You need to put your path="*"
route at the bottom of the Switch
otherwise it'll match everything and anything below it won't even have a chance to match since Switch
es match only a single route. The description of making sure you have your route path set up correctly (below) is applicable as well, of course.
<Switch>
<Route path="/show/:name?" component={ShowRouteParam} />
<Route path="*">ERROR 404</Route>
</Switch>
https://codesandbox.io/s/elated-browser-d0sew?file=/src/App.js
The routes don't match query parameters.
"Please note: The RegExp returned by path-to-regexp is intended for use with pathnames or hostnames. It can not handle the query strings or fragments of a URL."
Depending on how you want to do it, you can either make the id an optional part of the route, or let it be a normal query parameters
Option 1:
<Route path="/show/:name?" component={Show}></Route>
component:
import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
componentDidMount(){
console.log(this.props.location.search);
const values = queryString.parse(this.props.location.search);
console.log(values.name);
}
render() {
const { params } = this.props.match;
return <div>
<h4>About</h4>
<p>This is About page.</p>
{params.name ? <b>ID: {params.name}</b> : <i>Name is optional.</i>}
</div>
}
}
export default Show;
Option 2:
<Route path="/show" component={Show}></Route>
component:
import React, { Component } from 'react';
import queryString from 'query-string';
class Show extends Component {
componentDidMount(){
console.log(this.props.location.search);
const values = queryString.parse(this.props.location.search);
console.log(values.name);
}
render() {
const values = queryString.parse(this.props.location.search);
return <div>
<h4>About</h4>
<p>This is About page.</p>
{values.name ? <b>ID: {values.name}</b> : <i>Name is optional.</i>}
</div>
}
}
export default Show;
Working example: https://codesandbox.io/s/silent-rain-n61zs
Upvotes: 2
Reputation: 202658
path="show(/:name)"
This isn't a valid URL path to match on.
Redefine the path to ["/show/:id", "/show"]
<Route path={["/show/:id", "/show"]} name="name" component={Show} />
And since the Route
is directly rendering the component, it can pull the query parameters and match parameters straight from props (this.props.match.params
& this.props.location.search
). Specifying two matching paths is equivalent to defining two separate Route
s that render the same component. The same rules apply to path specificity, so define more complex matches first within the array.
class Show extends Component {
componentDidMount(){
console.log(this.props.location.search);
const values = queryString.parse(this.props.location.search);
console.log(values.name);
}
render() {
const { params } = this.props.match;
return <div>
<h4>About</h4>
<p>This is About page.</p>
{params.id ? <b>ID: {params.id}</b> : <i>ID is optional.</i>}
</div>
}
}
Upvotes: 1