1
votes

I am using react router V6 and have been following this tutorial for routing setup: https://blog.logrocket.com/react-router-v6/ but the view won't update when I click on the links in navigation menu.

visiting localhost:3000/Crime renders right component.
visiting localhost:3000/ renders right component.

but when clicking on the links, the view won't get updated, but the url path does.

GameComponent:

import React, { Component } from "react";
//import Component from 'react-dom';
import SideBarRight from "./components/game/sideBarRight.jsx";
import SideBarLeft from "./components/game/sideBarLeft.jsx";
import Crime from "./components/game/crime.jsx";

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

class GameComponent extends Component {
  constructor() {
    super();
    this.state = { color: "red" };
  }

  render() {
    return (
      <div className="main">
        data testing:
        <Router>
          <nav style={{ margin: 10 }}>
            <Link to="/" style={{ padding: 5 }}>
              Home
            </Link>
            <Link to="/crime" style={{ padding: 5 }}>
              Crime
            </Link>
          </nav>
          <Route path="/" element={<SideBarRight />} />
          <Route path="/crime" element={<Crime />} />
        </Router>
      </div>
    );
  }
}

export default GameComponent;

Crime component:

import React, { Component } from "react";
//import Component from 'react-dom';
import "./../../gameComponent.css";

class Crime extends Component {
  constructor() {
    super();
    this.state = {
      color: "red",
      user: {
        cash: 0,
        bank: 0,
        weapon: "",
        username: "test",
        locationname: "Bankok",
        defence: 0,
      },
      rankbar: { rankpercent: 50, rank: "Mafia" },
    };
  }

  render() {
    return <span>crimeday</span>;
  }
}

export default Crime;

Sidebar:

import React, { Component } from "react";
//import Component from 'react-dom';
import "./../../gameComponent.css";
import {
  BrowserRouter,
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
} from "react-router-dom";

class SideBarLeft extends Component {
  constructor() {
    super();
    this.state = { color: "red" };
  }

  render() {
    return (
      <div className="content_sidebar">
        <div className="header">
          <span>Computerbar1</span>
        </div>
        <BrowserRouter>
          <ul>
            <li>
              <Link to="/">Clear</Link>
            </li>
            <li>
              <Link to="/crime">Crime</Link>
            </li>
          </ul>
        </BrowserRouter>
      </div>
    );
  }
}

export default SideBarLeft;
3

3 Answers

0
votes

For react-router v5:

Use Switch and exact:

<Switch>
  <Route exact path="/" element={<SideBarRight />} />
  <Route exact path="/crime" element={<Crime />} />
</Switch>

Switch renders the first child Route or Redirect that matches the location. And when exact is true, the route will only match if the path matches the location.pathname exactly.

You should not use exact when your route has nested child routes, for example, if you have /crimes/summary or /crimes/details etc as child routes inside /crimes.


If you are using react-router v6, as explained here, you replace Switch with Routes and you don't need to use exact because all <Route> paths match exactly by default:

<BrowserRouter>
  <nav style={{ margin: 10 }}>
    <Link to="/" style={{ padding: 5 }}>
      Home
    </Link>
    <Link to="/crime" style={{ padding: 5 }}>
      Crime
    </Link>
  </nav>
  <Routes>
    <Route path="/" element={<SideBarRight />} />
    <Route path="/crime" element={<Crime />} />
  </Routes>
</BrowserRouter>

Also, you don't need to use BrowserRouter more than once, so your SideBarRight may look like:

function SideBarRight() {
  return (
    <div className="content_sidebar">
      <div className="header">
        <span>Computerbar1</span>
      </div>
      {/* <BrowserRouter> -> NOT REQUIRED */}
      <ul>
        <li>
          <Link to="/">Clear</Link>
        </li>
        <li>
          <Link to="/crime">Crime</Link>
        </li>
      </ul>
      {/* </BrowserRouter> */}
    </div>
  );
}
0
votes

You could try adding exact to your Route like this

<Route exact path="/" element={<SideBarRight />} />
<Route path="/crime" element={<Crime />} />

The reason being "/" and "/crime" both starts with /, and without the exact keyword, React thinks they are both the same path.

EDIT: More information on exact here https://reactrouter.com/web/api/Route/exact-bool

0
votes

First, I guess you are using React router V6 version here, if it was the stable V5 version, above solutions using <Switch>, 'exact' would work absolutely fine.

The errors I see in your code are:

  1. In GameComponent enclose the <Route> paths using <Routes> as follows, otherwise '/' will match both '/' and '/crime'
      <Routes>
           <Route path="/" element={<SideBarRight />} />
           <Route path="/crime" element={<Crime />} />
      </Routes>
  1. Remove <BrowserRouter> from <SideBarRight> component, it should be added only once for the application