Search code examples
javascriptreactjsreact-routerreact-router-domnavbar

Link components to own Navbar


I build my own Navbar using a YT-Tutorial and now I'm trying to connect the different sections of the website using react-router-dom. But when I click the Navbar in the browser it shows nothing, I don't get what I'm doing wrong.

App.js:

import './App.css';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Navbar from './components/Navbar/Navbar'
import Home from './components/Home/Home'
import Blog from './components/Blog/Blog'
import About from './components/About/About'

function App() {
  return (
    <div className="App">
      <Router>
        <Navbar />
        <Routes>
          <Route path='/components/Home/Home' component={Home} />
          <Route path='/components/Blog/Blog' component={Blog} />
          <Route path='/components/About/About' component={About} />
        </Routes>
      </Router>
    </div>
  );
}

export default App;

Navbar.js:

import React, { Component } from 'react';
import { MenuItems } from './MenuItems';
import './Navbar.css'
import { Button } from '../Button'
import { NavLink as Link } from 'react-router-dom'

class Navbar extends Component {
    state = {
        clicked: false
    }

    handleClick = () => {
        this.setState({ clicked : !this.state.clicked })
    }

    render() {
        return(
            <nav className="NavbarItems">
                <h1 className="navbar-logo">Afrika-Link</h1>
                <div className="menu-icon" onClick={this.handleClick}>
                    <i className={this.state.clicked ? 'fas fa-times' : 'fas fa-bars'}></i>
                </div>
                <ul className={this.state.clicked ? 'nav-menu active' : 'nav-menu'}>
                    {MenuItems.map((item, index) => {
                        return (
                            <li key={index}>
                                <a className={item.cName} href={item.url}>
                                    {item.title}    
                                </a>
                            </li>
                        )
                    })}
                </ul>
                <Button>Sign Up</Button>
            </nav>
        )
    }
}

export default Navbar

Home.js:

import React, { Component } from 'react';

class Home extends Component {
  render() {
    return (
      <p>Home</p>
    );
  }
}

export default Home

(The sections until now all look like this, so there's only minimal content to check if they get displayed or not)

MenuItems.js:

export const MenuItems = [
    {
        title: 'Home',
        url: '../Home/Home',
        cName: 'nav-links'
    },
    {
        title: 'Blog',
        url: '../Blog/Blog',
        cName: 'nav-links'
    },
    {
        title: 'About',
        url: '../About/About',
        cName: 'nav-links'
    },
    {
        title: 'Sign up',
        url: '#',
        cName: 'nav-links-mobile'
    }
]

I already tried to substitute the a with href in Navbar.js with Link but it didn't fix the issue.


Solution

  • Issues

    • react-router-dom@6 Route components render their content on the element prop. The element prop takes a React.ReactNode, a.k.a. JSX.
    • The routes rendered and the links to them should agree on path.
    • The Navbar component should render RRD Link components instead of raw anchor <a> tags. The link target path is specified on the to prop.

    A Suggested Solution

    App.jsx

    import './App.css';
    import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
    import Navbar from './components/Navbar/Navbar'
    import Home from './components/Home/Home'
    import Blog from './components/Blog/Blog'
    import About from './components/About/About'
    
    function App() {
      return (
        <div className="App">
          <Router>
            <Navbar />
            <Routes>
              <Route path="/home" element={<Home />} />
              <Route path="/blog" element={<Blog />} />
              <Route path="/about" element={<About />} />
    
              {/* Redirect all unhandled paths to home page */}
              <Route path="*" element={<Navigate to="/home" replace />} />
            </Routes>
          </Router>
        </div>
      );
    }
    
    export default App;
    

    menuItems.js

    export const menuItems = [
      {
        title: 'Home',
        url: '/home',
        cName: 'nav-links'
      },
      {
        title: 'Blog',
        url: '/blog',
        cName: 'nav-links'
      },
      {
        title: 'About',
        url: '/about',
        cName: 'nav-links'
      },
      {
        title: 'Sign up',
        url: '#',
        cName: 'nav-links-mobile'
      }
    ];
    

    Navbar.jsx

    import React, { useState } from 'react';
    import { MenuItems } from './MenuItems';
    import './Navbar.css'
    import { Button } from '../Button'
    import { NavLink as Link } from 'react-router-dom'
    
    const Navbar = () => {
      const [clicked, setClicked] = React.useState(false);
    
      const handleClick = () => {
        setClicked(clicked => !clicked);
      }
    
      return (
        <nav className="NavbarItems">
          <h1 className="navbar-logo">Afrika-Link</h1>
          <div className="menu-icon" onClick={handleClick}>
            <i className={clicked ? 'fas fa-times' : 'fas fa-bars'} />
          </div>
          <ul className={clicked ? 'nav-menu active' : 'nav-menu'}>
            {MenuItems.map((item, index) => (
              <li key={index}>
                <Link className={item.cName} to={item.url}>
                  {item.title}    
                </Link>
              </li>
            ))}
          </ul>
          <Button>Sign Up</Button>
        </nav>
      );
    };
    
    export default Navbar