Alex Ironside
Alex Ironside

Reputation: 5039

React Router <Component/> vs {Component}

I have a list of items. When user clicks on one of the items, it takes him to a page with only this element. Like this:

Questions component:

render() {
    return (
        <section id='loopContainer' className='display-question'>
            <div className='wrapper'>
                <ul style={{listStyleType: 'none'}}>
                    {
                        this.state.questions.map(question => {
                            return (
                                <li key={question.id}>
                                    <h3>Kategoria: {question.category}</h3>
                                    <p>Poziom: {question.level}</p>
                                    <p>Punkty: {question.pointAmount + question.pointBoost}</p>
                                    <img alt='' style={{width: '20%'}} src={question.photoURL}/>
                                    <p>{question.workText}</p>
                                    <Link to={`/question/${question.id}`}
                                          style={{display: 'block', margin: 'auto'}}>Rozwiaz to zadanie
                                    </Link>
                                </li>
                            )
                        })
                    }
                </ul>
            </div>
        </section>
    )
}

Question component:

render() {
    return (
        this.state.questions.map(question => {
            return (
                <section key={question.id} className='display-question'>
                    <div className='wrapper show-grid'>
                        <h3>Kategoria: {question.category}</h3>
                        <p>Poziom: {question.level}</p>
                        <p>Punkty: {question.pointAmount + question.pointBoost}</p>
                        <Col xs={12} md={6}>
                            <img alt='' style={{width: '100%'}}
                                 src={question.photoURL}/>{/*Need 100% for the ratio*/}
                            <p>{question.workText}</p>
                        </Col>
                        <Col xs={12} md={6}>
                            <form onSubmit={this.handleSubmit}>
                                <textarea name="textAnswer" id="textAnswer" style={{
                                    width: '100%',
                                    height: '50vh',
                                    background: 'white',
                                    color: 'black'
                                }}/>
                                <input id="file-upload" type="file"/>
                                <Button type='submit' style={{display: 'block'}}>Wyslij odpowiedz</Button>
                            </form>
                        </Col>
                    </div>
                </section>
            )
        })
    )
}

This is how I'm trying to query the database:

const itemsRef = firebase.database().ref('Works')
                         .orderByChild('firebaseKey')
                         .equalTo(this.props.match.params.id);

The problem is in my Navigation component. Exactly here:

<Switch>
    <Route exact path="/about" component={AboutComponent}/>

    <Route exact path="/questions" render={
        () => (firebase.auth().currentUser === null ?
            <Redirect to='/'/> : <QuestionsComponent/>)
    }/>

    <Route exact path='/question/:id' render={
        () => (firebase.auth().currentUser === null ?
            <Redirect to='/'/> : <QuestionComponent/>)
    }/>

    <Route exact path="/" component={HomeComponent}/>
</Switch>

So the problem is, when I'm trying to get to the single element page, this throws an error:

<Route exact path='/question/:id' render={
    () => (firebase.auth().currentUser === null ?
        <Redirect to='/'/> : <QuestionComponent/>)
}/>

The error is: TypeError: this.props.match is undefined.

But if I do it like this:

<Route exact path='/question/:id' component={QuestionComponent}/>

All works well.

So why is the first way erroring out, while the second is just fine? And how do I make the second way work?

Upvotes: 0

Views: 55

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281646

When you use the render prop, it gives you the Router props as params which you need to pass down to you custom component which uses them like

<Route exact path="/questions" render={
    (props) => (firebase.auth().currentUser === null ?
        <Redirect to='/'/> : <QuestionsComponent {...props}/>)
}/>

In case of a component prop, Route automatically passes the Router props to the underlying component.

Upvotes: 1

Related Questions