0

Hope you're going great :)

My React Router is not responding to changes in URL through params. Here's the App.js:

import React, { useContext } from "react";
import { Switch, Route } from "react-router";
import NavBar from "../Navbar/Navbar";
import Homepage from "../Homepage/Homepage";
import Shops from "../Shops/Shops";
import Products from "../Products/Products";
import Games from "../Games/Games";
import Gamepage from "../Commons/Gamepage";

const App = () => {
  
  return (
    <React.Fragment>
      <NavBar token={token} />
      <Switch>
        <Route path="/homepage" component={Homepage} />
        <Route path="/shops" component={Shops} />
        <Route path="/products" component={Products} />
        <Route path="/games" component={Games} />
        <Route
          path={`/games/:id`}
          render={(props) => <Gamepage {...props} />}
        />
        <Route path="/" component={Homepage} />
      </Switch>
    </React.Fragment>
  );
};

export default App;

Here's the Gamepage:

import React from "react";

const Gamepage = () => {
  return <h1>Hello</h1>;
};
export default Gamepage;

And here's the link:

<Link to="/games/euromillions">
        <div className="games-list">
          <h4>Euromillions</h4>
          <img src={euro} alt="euro" />
        </div>
      </Link>

Every other Link (like in Navbar) is working... But when I click this specific link, it doesn't work, stays in Games page :/

I've tried:

  1. Change params name;
  2. Change Gamepage component to something else;
  3. Change Link tag to other place (doesn't work with params);

3 Answers3

2

The reason why it stays on the games page is that you have multiple links with similar names. What you can do is use the exact keyword to match the exact same route that you want to navigate your user to. You can read this question it has answered with the explanation of how and where we should use the exact keyword.

Prince Mittal
  • 126
  • 1
  • 7
2

When the react router checks for links in the Switch component, it checks if the url in the browser starts with the links defined in the Route component and goes to the first matching route. So when the url in the browser is /games/euromillions, react router goes through all the links defined in the Route component and in your case when it reaches at the /games route it stops there since /games/euromillions, starts with /games and then renders that component. It never reaches the /games/:id route. There are two options to fix this.

  1. You either place the /games/:id route above the /games route.
import React, { useContext } from "react";
import { Switch, Route } from "react-router";
import NavBar from "../Navbar/Navbar";
import Homepage from "../Homepage/Homepage";
import Shops from "../Shops/Shops";
import Products from "../Products/Products";
import Games from "../Games/Games";
import Gamepage from "../Commons/Gamepage";

const App = () => {
  
  return (
    <React.Fragment>
      <NavBar token={token} />
      <Switch>
        <Route path="/homepage" component={Homepage} />
        <Route path="/shops" component={Shops} />
        <Route path="/products" component={Products} />
        <Route
          path={`/games/:id`}
          render={(props) => <Gamepage {...props} />}
        />
        <Route path="/games" component={Games} />
        <Route path="/" component={Homepage} />
      </Switch>
    </React.Fragment>
  );
};

export default App;
  1. You add the exact option to the /games route
import React, { useContext } from "react";
import { Switch, Route } from "react-router";
import NavBar from "../Navbar/Navbar";
import Homepage from "../Homepage/Homepage";
import Shops from "../Shops/Shops";
import Products from "../Products/Products";
import Games from "../Games/Games";
import Gamepage from "../Commons/Gamepage";

const App = () => {
  
  return (
    <React.Fragment>
      <NavBar token={token} />
      <Switch>
        <Route path="/homepage" component={Homepage} />
        <Route path="/shops" component={Shops} />
        <Route path="/products" component={Products} />
        <Route path="/games" component={Games} exact/>
        <Route
          path={`/games/:id`}
          render={(props) => <Gamepage {...props} />}
        />
        <Route path="/" component={Homepage} />
      </Switch>
    </React.Fragment>
  );
};

export default App;
Sparrow
  • 36
  • 1
1

You should put an exact before the first /game url catcher. So that it does not catch all the urls that start with "game"

const App = () => {
  
  return (
    <React.Fragment>
      <NavBar token={token} />
      <Switch>
        <Route path="/homepage" component={Homepage} />
        <Route path="/shops" component={Shops} />
        <Route path="/products" component={Products} />
        <Route exact path="/games" component={Games} />
        <Route
          path={`/games/:id`}
          render={(props) => <Gamepage {...props} />}
        />
        <Route path="/" component={Homepage} />
      </Switch>
    </React.Fragment>
  );
};