I have these routes
<Route exact path={`/admin/caters/:id`} ponent={Cater} />
<Route exact path={'/admin/caters/create'} ponent={CreateCater} />
When I navigate to the first route I get a cater with a given ID. And the Cater ponent is rendered
When I navigate to the second route, the CreateCater ponent is rendered on the page, but I noticed that some redux actions that are used in the Cater ponent are being run. So both ponent are somehow being rendered - but I can't figure out why.
Here are the ponents:
Cater:
class Cater extends Component {
async ponentDidMount() {
console.log('Cater ponent did mount')
const { match: { params: { id }}} = this.props
this.props.get(id)
}
render() {
const { cater } = this.props
if(!cater) {
return null
}
else {
return (
<div>
... ponent data ...
</div>
)
}
}
}
const mapStateToProps = (state, props) => {
const { match: { params: { id }}} = props
return {
cater: caterSelectors.get(state, id)
}
}
const mapDispatchToProps = (dispatch, props) => {
return {
get: (id) => dispatch(caterActions.get(id))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Cater)
CreateCater:
export default class CreateCaterPage extends Component {
render() {
return (
<React.Fragment>
<Breadcrumbs />
<CaterForm />
</React.Fragment>
)
}
}
When I go to /admin/caters/create' I can see the console.log in the ponenDidMount() lifecycle method inside the Cater ponent.
I cant figure out what I am doing wrong :(
I have these routes
<Route exact path={`/admin/caters/:id`} ponent={Cater} />
<Route exact path={'/admin/caters/create'} ponent={CreateCater} />
When I navigate to the first route I get a cater with a given ID. And the Cater ponent is rendered
When I navigate to the second route, the CreateCater ponent is rendered on the page, but I noticed that some redux actions that are used in the Cater ponent are being run. So both ponent are somehow being rendered - but I can't figure out why.
Here are the ponents:
Cater:
class Cater extends Component {
async ponentDidMount() {
console.log('Cater ponent did mount')
const { match: { params: { id }}} = this.props
this.props.get(id)
}
render() {
const { cater } = this.props
if(!cater) {
return null
}
else {
return (
<div>
... ponent data ...
</div>
)
}
}
}
const mapStateToProps = (state, props) => {
const { match: { params: { id }}} = props
return {
cater: caterSelectors.get(state, id)
}
}
const mapDispatchToProps = (dispatch, props) => {
return {
get: (id) => dispatch(caterActions.get(id))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Cater)
CreateCater:
export default class CreateCaterPage extends Component {
render() {
return (
<React.Fragment>
<Breadcrumbs />
<CaterForm />
</React.Fragment>
)
}
}
When I go to /admin/caters/create' I can see the console.log in the ponenDidMount() lifecycle method inside the Cater ponent.
I cant figure out what I am doing wrong :(
Share Improve this question asked Nov 8, 2018 at 18:01 RoiRoi 1,00310 silver badges17 bronze badges 2-
Try swapping the
<Route />
tags (Put /create first), and let me know if that changes anything – Blue Commented Nov 8, 2018 at 18:04 -
Thank you for the reply @FrankerZ. I tried it and it didn't make any difference. I tried making url's different in length, so that create was looking like
/admin/cater/create/cater
. And then I didn't have any issues, but that is not how I want to structure my URL – Roi Commented Nov 8, 2018 at 18:12
2 Answers
Reset to default 7/create
matches /:id
, so it makes sense that this route matches. I remend forcing :id
to look for numeric only:
<Route exact path={`/admin/caters/:id(\\d+)`} ponent={Cater} />
<Route exact path={'/admin/caters/create'} ponent={CreateCater} />
Likewise, you can follow @jabsatz's remendation, use a switch, and have it match the first route that matches. In this case, you would need to ensure that the /admin/caters/create
route is the first <Route />
element matched.
The problem is that :id
is matching with create
(so, it thinks "see cater with id create
"). The way to solve this is to put the wildcard matching route last, and wrapping all the <Routes/>
with a <Switch/>
, so it only renders the first hit.
Check out the docs if you have any more questions: https://reacttraining./react-router/core/api/Switch