Search code examples
htmlreact-bootstrap

Passing a variable to a page in react-bootstrap


I have a site structured as below:

Public
 | index.html
src
  index.css
  index.js
  | components
      App.js
      Events.js
      Feed.js
      Detail.js
      Entry.js
      ...

Everything in <App /> is rendered in index.html

import React from 'react'
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { Navigation, Footer, Home, Feed, Search, About, Contact } from "../components";


function App() {
  return (
<Router>


      <Navigation />

      <Switch>
        <Route path="/" exact component={() => <Home />} />
        <Route path="/feed" exact component={() => <Feed />} />
        <Route path="/detail" exact component={() => <Detail />} />
        <Route path="/search" exact component={() => <Search />} />
        <Route path="/about" exact component={() => <About />} />
        <Route path="/contact" exact component={() => <Contact />} />
      </Switch>

      <Footer />

    </Router>
  )
}

export default App

The Feed component renders a series of Events each one of which has an event.id.

The event.id value is what I want to use to render the correct data in the component referenced by the Navigation / Switch above <Route path="/detail" exact component={() => <Detail />} />

How can I:

  1. Link to the Detail route and
  2. Pass the id of the event to the Detail component in that route
import React, {Component} from "react";
import Header from "./Header"
import Events from "./Events"

class Feed extends Component {

  state = {
  events: []
}

componentDidMount() {
  fetch('http://127.0.0.1:5002/events')
  .then(res => res.json())
  .then((data) => {

    this.setState({ events: data })

  })
  .catch(console.log)
}



render() {
  return (
    <div className="feed">
    <Header />
      <div class="container">

          <Events events={this.state.events} />
        
      </div>
    </div>
  );
}
}
export default Feed;
import React from 'react';
import Accordion from 'react-bootstrap/Accordion'
import Card from 'react-bootstrap/Card'
import Alert from 'react-bootstrap/Alert'
import Button from 'react-bootstrap/Button'
import './App.css'


function Events ({events}){


  return (
    <div>
      <center><h1>Event List</h1></center>
      {events.map((event) => (
        <div class="mt-2">

        <Accordion defaultActiveKey="0" className="rounded ">
          <Card className="rounded">
            <Accordion.Toggle as={Alert} variant="secondary" eventKey={event.id} className="accordion-title border-0"><span className="badge badge-secondary">{event.date}</span><span> </span><span>{event.title}</span>
            </Accordion.Toggle>
            <Accordion.Collapse eventKey={event.id} className="accordion-collapse">
            <Button href="detail" variant="secondary" size="lg" disabled>Link</Button>
              <Card.Body className="rounded">{event.summary}</Card.Body>
            </Accordion.Collapse>
          </Card>
        </Accordion>

        </div>
      ))}

    </div>
  )

}
export default Events;

The above three render as below:

enter image description here

And the Detail component below needs to accept the {route} value so I can call the API. I just don't know how to accept that value into the class when called.

import React, {Component} from "react";
import Detail from "./Detail"

class Detail extends Component {

  state = {
  entries: []
}

componentDidMount({route}) {
  fetch('http://127.0.0.1:5002/events/'+{route}+'/')
  .then(res => res.json())
  .then((data) => {

    this.setState({ entries: data })

  })
  .catch(console.log)
}



render() {
  return (
    <div className="entries">
    <Header />
      <div class="container">
        <div class="row align-items-center my-5">

          <Entry entry={this.state.entries} />
        </div>
      </div>
    </div>
  );
}
}
export default Detail;

Solution

  • Fixed this.

    The App.js was updated to include the variable in the switch as :event_id

      <Switch>
        <Route path="/" exact component={() => <Home />} />
        <Route path="/search/:query" exact component={() => <Search />} />
        <Route path="/feed" exact component={() => <Feed />} />
        <Route path="/detail/:event_id" component={Detail} />
        <Route path="/blog" exact component={() => <Blog />} />
        <Route path="/about" exact component={() => <About />} />
        <Route path="/contact" exact component={() => <Contact />} />
      </Switch>
    

    The link to the page was updated to include the path and event.id

    <div><span><Link to={`/detail/${event.id}`}>{event.title}</Link></span></div>
    

    And the Detail.js componentDidMount() called the props which matched the variable name:

    componentDidMount() {
    
      fetch('http://127.0.0.1:5002/events/'+this.props.match.params.event_id+'/entries')
      .then(res => res.json())
      .then((entryData) => {
    
        this.setState({ entries: entryData })
    
      })
      .catch(console.log)
    
    }