javascripthtmlreactjsreact-router

How to go to a page clicked on a hamburger menu?


I'm starting with an existing project called react-burger-menu.
https://github.com/negomi/react-burger-menu

It uses a hamburger menu sidebar for navigation. Unfortunately, the demo code does not show how to actually go to a specific clicked item page. Here is the example.js code that returns the sidebar menu:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import BurgerMenu from 'react-burger-menu';
import classNames from 'classnames';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHospitalUser,faHouseMedical } from '@fortawesome/free-solid-svg-icons'

class MenuWrap extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hidden: false
    };
  }

  componentDidUpdate(prevProps) {
    const sideChanged =
      this.props.children.props.right !== prevProps.children.props.right;

    if (sideChanged) {
      this.setState({ hidden: true });

      setTimeout(() => {
        this.show();
      }, this.props.wait);
    }
  }

  show() {
    this.setState({ hidden: false });
  }

  render() {
    let style;

    if (this.state.hidden) {
      style = { display: 'none' };
    }

    return (
      <div style={style} className={this.props.side}>
        {this.props.children}
      </div>
    );
  }
}

class Demo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentMenu: 'scaleDown',
      side: 'left'
    };
  }

  changeMenu(menu) {
    this.setState({ currentMenu: menu });
  }

  changeSide(side) {
    this.setState({ side });
  }

  getItems() {

     let  items = [
          <a key="0" href="">
            <FontAwesomeIcon icon={faHouseMedical} fixedWidth/>
            <span>Home</span>
          </a>,
          <a key="1" href="">
            <FontAwesomeIcon icon={faHospitalUser} fixedWidth/>
            <span>Medical History</span>
          </a>,
        ];

    return items;
  }

  getMenu() {
    const Menu = BurgerMenu[this.state.currentMenu];

    return (
      <MenuWrap wait={20} side={this.state.side}>
        <Menu
          id={this.state.currentMenu}
          pageWrapId={'page-wrap'}
          outerContainerId={'outer-container'}
          right={this.state.side === 'right'}
        >
          {this.getItems()}
        </Menu>
      </MenuWrap>
    );
  }

  render() {
    const buttons = Object.keys(this.props.menus).map(menu => {
      return (
        <a
          key={menu}
          className={classNames({
            'current-demo': menu === this.state.currentMenu
          })}
          onClick={this.changeMenu.bind(this, menu)}
        >
          {this.props.menus[menu].buttonText}
        </a>
      );
    });

    // The following returns hard-coded html. How to return code depending on what is clicked?
    return (
      <div id="outer-container" style={{ height: '100%' }}>
        {this.getMenu()}
        <main id="page-wrap">
          <h1>
            <a href="https://github.com/negomi/react-burger-menu">
              react-burger-menu
            </a>
          </h1>
          <h2 className="description">
            An off-canvas sidebar React component with a collection of effects
            and styles using CSS transitions and SVG path animations.
          </h2>
          <nav className="demo-buttons">{buttons}</nav>
        </main>
      </div>
    );
  }
}

const menus = {
  slide: { buttonText: 'Slide', items: 1 },
  scaleDown: { buttonText: 'Scale Down', items: 2 },
};

ReactDOM.render(<Demo menus={menus} />, document.getElementById('app'));

It contains two classes, MenuWrap and Demo. The Demo class's render() function returns hard-coded html. How to go to a different page depending on what is clicked in the menu?

Typically react uses a <Router> to do that in the index.js or app.js file, as in:

import { BrowserRouter as Router, Route, Link, Routes } from "react-router-dom";

I can't figure out how to reconcile these two methods. Can someone clarify?


Solution

  • I think you should try this. I hope this would help you

    import React, { Component } from 'react';
    import ReactDOM from 'react-dom';
    import { BrowserRouter as Router, Route, Link, Routes } from "react-router-dom";
    import { Menu } from './Menu';
    import { faClinic, faFileMedical } from '@fortawesome/free-solid-svg-icons';
    import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
    
    // Example components for different pages
    const Dashboard = () => <div>Dashboard Page</div>;
    const HealthRecords = () => <div>Health Records Page</div>;
    
    class MenuWrap extends Component {
      constructor(props) {
        super(props);
        this.state = { hidden: false };
      }
    
      componentDidUpdate(prevProps) {
        const sideChanged = this.props.children.props.right !== prevProps.children.props.right;
        if (sideChanged) {
          this.setState({ hidden: true });
          setTimeout(() => { this.show(); }, this.props.wait);
        }
      }
    
      show() {
        this.setState({ hidden: false });
      }
    
      render() {
        const style = this.state.hidden ? { display: 'none' } : {};
        return <div style={style} className={this.props.side}>{this.props.children}</div>;
      }
    }
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = { currentMenu: 'slide', side: 'left' };
      }
    
      changeMenu(menu) {
        this.setState({ currentMenu: menu });
      }
    
      changeSide(side) {
        this.setState({ side });
      }
    
      getItems() {
        return [
          <Link key="0" to="/">
            <FontAwesomeIcon icon={faClinic} fixedWidth />
            <span>Dashboard</span>
          </Link>,
          <Link key="1" to="/health-records">
            <FontAwesomeIcon icon={faFileMedical} fixedWidth />
            <span>Health Records</span>
          </Link>,
        ];
      }
    
      getMenu() {
        const MenuComponent = Menu[this.state.currentMenu];
        return (
          <MenuWrap wait={20} side={this.state.side}>
            <MenuComponent
              id={this.state.currentMenu}
              pageWrapId={'page-wrap'}
              outerContainerId={'outer-container'}
              right={this.state.side === 'right'}
            >
              {this.getItems()}
            </MenuComponent>
          </MenuWrap>
        );
      }
    
      render() {
        const buttons = Object.keys(this.props.menus).map(menu => (
          <a
            key={menu}
            className={classNames({ 'current-demo': menu === this.state.currentMenu })}
            onClick={() => this.changeMenu(menu)}
          >
            {this.props.menus[menu].buttonText}
          </a>
        ));
    
        return (
          <Router>
            <div id="outer-container" style={{ height: '100%' }}>
              {this.getMenu()}
              <main id="page-wrap">
                <h1>
                  Health Care App
                </h1>
                <h2 className="description">
                  A simple health care app with a responsive menu
                </h2>
                <nav className="demo-buttons">{buttons}</nav>
                <Routes>
                  <Route path="/" element={<Dashboard />} />
                  <Route path="/health-records" element={<HealthRecords />} />
                </Routes>
              </main>
            </div>
          </Router>
        );
      }
    }
    
    const menus = {
      slide: { buttonText: 'Slide', items: 1 },
      scaleDown: { buttonText: 'Scale Down', items: 2 },
    };
    
    ReactDOM.render(<App menus={menus} />, document.getElementById('app'));