最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React router v4 - Rendering two components on same route - Stack Overflow

programmeradmin2浏览0评论

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
Add a ment  | 

2 Answers 2

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

发布评论

评论列表(0)

  1. 暂无评论