0
votes

I'm working on the main page of a website and I'd like to have a specific nav/menu bar for the main page and a different one for the other components (the main page hides de "home" button and the others show it).

The issue I have at the moment is that the logic of rendering this menu lives on App and I'm having a hard time to find the proper way to pass the state of my App component to the other components, probably just because of the lack of experience.

import React from "react";
import { BrowserRouter, Route, Link } from "react-router-dom";
import Main from "./main";
import MapContainer from "./mapcontainer";
import Venue from "./venue";
import Schedule from "./schedule";
import Accommodation from "./accommodation";
import Couple from "./couple";
import Honeymoon from "./honeymoon";
import Uploader from "./uploader";
import Friday from "./friday";
import Saturday from "./saturday"
import Sunday from "./sunday";
import Dresscode from "./dresscode";

export class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            error: false,
            isHome: true
        };        
    }

    componentDidMount() {
        console.log("App mounted");
    }


    render() {

        function HomeComponentMenu(props) {
            return (
                <nav className="header-on-app">
                    <button>Contact Us</button>
                    <button className="logout-btn"><a href="/logout">Logout</a></button>
                </nav>
            );
        }

        function AllOtherComponentsMenu(props) {
            return (
                <nav className="header-on-app">
                    <button><Link to="/">Home</Link></button>
                    <button>Contact Us</button>
                    <button className="logout-btn"><a href="/logout">Logout</a></button>
                </nav>
            );
        }

        const isHome = this.state.isHome;
        let menu;

        if (isHome) {
            menu = <HomeComponentMenu/>;
        } else {
            menu = <AllOtherComponentsMenu/>;
        }

        return (
            <BrowserRouter>

              <nav className="header-on-app">{menu}</nav>
                <div className="app-container">     
                    <Route exact path="/" component={Main} />
                    <Route exact path="/venue" component={Venue}/>
                    <Route exact path="/venuemap" component={MapContainer}/>
                    <Route exact path="/schedule" component={Schedule}/>
                    <Route exact path="/accommodation" component={Accommodation}/>
                    <Route exact path="/couple" component={Couple}/>
                    <Route exact path="/honeymoon" component={Honeymoon}/>
                    <Route exact path="/uploader" component={Uploader} />
                    <Route exact path="/friday" component={Friday} />
                    <Route exact path="/saturday" component={Saturday} />
                    <Route exact path="/sunday" component={Sunday} />
                    <Route exact path="/dresscode" component={Dresscode} />
                </div>
            </BrowserRouter>
        );
    }
}

Component I'd like to set isHome to false

import MapContainer from "./mapcontainer";


export default class Venue extends React.Component {
    constructor(props){
        super(props);

        this.state = {
            error:false,
        }
    }
    render() {
        return (
            <div className="venue-container">

            <h1>Anna & Rodolfo</h1>
            <h2><span>_______</span> Venue . Local . Veranstalungsort <span>_______</span></h2>
            {this.state.error && <h2 className="error">Ops! Something went wrong.</h2>}

            <div className="grid-container-venue">


                    <div className="item">
                    <img src="venue.png" alt="Avatar" className="image"/> 
                    <div className="background-grid-items">
                    <div className="text-address">
                    <a href="https://www.g71972,15z/data=!4887b!8m2!3d52.47094!4d12.71972">
                        <p>Kulturschloss</p>
                        <p>Abcd.30 3456 Berlin </p>
                        <p>Germany . Alemanha . Deutschland</p>
                    </a>    
                    </div>
                    </div>
                    </div>

                    <div className="item">
                    <img src="website.png" alt="Avatar" className="image"/> 
                    <div className="background-grid-items">
                    <div className="text">
                    <a href="https://www.kult.de/">   
                        <p>To the Website</p>
                        <p>Para o Website</p>
                        <p>Zur Website</p>
                    </a>    
                    </div>
                    </div>
                    </div>

                    <div className="item">
                    <img src="transportation.png" alt="Avatar" className="image"/>    
                    <div className="background-grid-items">
                    <div className="text">
                        <p>Transportation</p>
                        <p>Traslado</p>
                        <p>Transport</p>
                    </div>
                    </div>
                    </div>

                    <div className="item">
                        <div className="background-grid-venue">
                            <div className="map">
                            <MapContainer/>
                            </div>
                        </div>
                    </div>

            </div>
        </div>

        );
    }
}

Since my components are being rendered by React Router, I tried to render props passing it in an inline function and afterwards pass along to the argument I was creating, but somehow it didn't work. Would you have any suggestions on how to solve this? Thank you very much!

2

2 Answers

0
votes

To pass a state to a child component, you have to pass it as props of the child component.

e.g.

import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import TableView from './TableView'

export default class App extends Component {
  state = {
    item: 'this is the item'
  }

render() {
  return(
    <Router>
      <Route exact path="/home">
        <TableView itemList={this.state.item}></TableView>
      </Route>
    </Router>
  )
}

}

to get the props in the child component

import React, { Component } from 'react'

export default class TableView extends Component {
  render(){
    <React.Fragment>
      {this.props.item}
    </React.Fragment>
  }
}

Hope it helps

EDIT: It would also help to debug if you have the react devtools addons in your browser to check if the values of the state of each component

0
votes

To pass props to a react route you have to define it in the render function like this:

<Route exact path="/venue" render={(props) => <Venue updateHomeState={this.updateHomeState}/>}/>

To alter the isHome state on the parent, you could define that function on the parent like:

updateHomeState = (newState) => { 
    this.setState({ isHome: newState }) 
} 

And then call it in componentDidMount() of your child component like this.props.updateHomeState(newState).