7

So what I want is to have a top-level routing in App.js that routes to Home on "/". In Home i want to render a few things and then one place where I chose what to render based on the path.

i.e. if the path is "/" I want to show a Link that can take me to "/about", if the path is "/about" I'll show the About component there.

In App.js I always have a Link that can take me back to "/".


So App.js render this:

  <Router>
    <div>          
      <Link to="/">
        <button>Go to home</button>
      </Link>
      <Route exact path="/" component={() => <Home/>} />
      <Route exact path="/other" component={() => <Other/>} />
    </div>
  </Router>

Home render this:

  <div>
    THIS IS HOME WOO!
    <Router>
      <div>
        <Route exact path="/" component={() => <HomeController/>} />
        <Route exact path="/about" component={() => <About/>} />
      </div>
    </Router>
  </div>

HomeController render this:

  <Link to="/about">
    <button>Go to about</button>
  </Link>

and About render this:

  <div>
    ABOUT
  </div>

When I start the app it looks like this:

enter image description here

When I click 'Go to about' it looks like this:

enter image description here

correctly updating the url and what is showed by the router in Home

But if I now click on 'Go to home' this happens:

enter image description here

correctly updating the url but keeping the 'about' page when rendering Home?


Why is this? Why does "/" seem to still route to "/about"? What would I need to change to make the button route back to "/" and show the 'Go to about'-button again?

Here is all the code I used to recreate the issue: pastebin

iceveda06
  • 601
  • 8
  • 21
MrJalapeno
  • 1,532
  • 3
  • 18
  • 37
  • Why are you using two different `` components here? If you just remove the `` inside your `Home` component it should work how you want it to. You don't need a new `` as parent every time you want to define routes. The Router can be a distant parent and it will still work. – Raicuparta Apr 19 '18 at 12:54
  • Oh! Thank you, I should obviously spend more time learning how react-router-dom works. On mobile now but will try it out in a few minutes – MrJalapeno Apr 19 '18 at 12:57
  • Alright, I removed the `` component in `Home` but then it doesn't look like it's rendering `About` inside of `Home`. More specifically, when clicking 'Go to about' the "THIS IS HOME WOO!" disappear and is completely replaced by "ABOUT". – MrJalapeno Apr 19 '18 at 13:08

3 Answers3

3

There are a few things that you need to correct.

First, you must have just a single Router in your App and not nested Router

Second, If you have an exact keyword on the parent Route then the nested Routes won't match since the match will fails at the parent itself

Third, Then you don't want to pass custom props to the child component, you must render them like component={Home} and not component={() => <Home/>} and if you want to pass props to children, you must use render and not component prop and write render={(props) => <Home test="1" {...props}}

Your complete code will look like

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

class App extends Component {
  render() {
    return (
      <div className="App">
        <Router>
          <div>
            <Link to="/">
              <button>Go to home</button>
            </Link>
            <Route path="/" component={Home} />
            <Route exact path="/other" component={Other} />
          </div>
        </Router>
      </div>
    );
  }
}

class Home extends Component {
  render() {
    return (
      <div className="home">
        <div>
          <Route exact path="/" component={HomeController} />
          <Route exact path="/about" component={About} />
        </div>
      </div>
    );
  }
}

class HomeController extends Component {
  render() {
    return (
      <div className="homecontroller">
        <Link to="/about">
          <button>Go to about</button>
        </Link>
      </div>
    );
  }
}

class About extends Component {
  render() {
    return <div className="about">ABOUT</div>;
  }
}

class Other extends Component {
  render() {
    return <div className="other">OTHER</div>;
  }
}

render(<App />, document.getElementById("root"));

Working demo

You can refer the following question for more details

Passing custom props to router component in react-router v4

React Router 4 Nested Routes not rendering

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Thanks for a great answer! The first two points fixed the problem. A question on the last part though: why is that? For example in my real code I now have this route: ` – MrJalapeno Apr 20 '18 at 06:00
  • @MrJalapeno, It sure works, however its a good practice to use render, please refer to the first link that I added in my answer, it will explain you as to why you need `{...props}` – Shubham Khatri Apr 20 '18 at 06:03
1

Delete the <Router /> entries from Home

Make the following adjustments to App.js I noticed /other was listed instead of About component for /about Route. If it's correct leave it alone otherwise adjust it to About component as below. You do need to import these components at the top so i'm assuming you are already doing this.

  <Router>
    <div>          
      <Link to="/">
        <button>Go to home</button>
      </Link>
      <Route exact path="/" component={Home} />
      <Route exact path="/about" component={About} />
    </div>
  </Router>

for Home.js, you need to render <HomeController />

  <div>
    THIS IS HOME WOO!
    <HomeController />
  </div>
iceveda06
  • 601
  • 8
  • 21
  • Thanks but it didn't fix my pickle :( On "/about" I want to render `About` _inside_ of `Home`, that is, I want to see both the content of `Home` ("THIS IS HOME WOO") and the content of `About` ("ABOUT") where it replaces the HomeController (the "Go to about"-button) I'm wondering if I'm taking some fundamental wrong path for solving this issue. – MrJalapeno Apr 19 '18 at 15:58
0

I needed to make the following changes:

App.js: Change Router to Switch, change the order of the Routes and set "/" to a relative path

<Switch>
  <Route exact path="/other" component={() => <Other/>} />
  <Route path="/" component={() => <Home/>} />
</Switch>

Remove the Router from Home:

<div>
  THIS IS HOME WOO!
  <div>
      <Route exact path="/" component={() => <HomeController/>} />
      <Route exact path="/about" component={() => <About/>} />
  </div>
</div> 
MrJalapeno
  • 1,532
  • 3
  • 18
  • 37