Darren Barklie
Darren Barklie

Reputation: 117

React-Router v4 separating Link and Route path elements

(Updated for clarity) I have the following structure for my App:

<Layout />
  /components/
    <Header /> 
    <Navigation />
    <Stage />
    <Footer />
  /pages/
    <Home />
    <About />
    <Contact />

My thinking is to have the <Navigation> element isolated, and imported into the parent <Header> (and later, Site Map). All components are then staged into the parent <Layout>, which is fed into the <div id="root">

The content of my /pages/ Components are successfully called and rendered with the code below. However this page content is rendered inside of my <header> element, breaking the page hierarchy.

My intention is to have the <Switch> device render the /pages/ Components within the <Stage> parent Component.

Any attempt to move the <Switch> element to the <Stage> component causes the whole app to not load/render.

import React from 'react';

import {
  BrowserRouter as Router, Route, Link, Switch
} from 'react-router-dom';


import Home from './../pages/Home';
import About from './../pages/About';
import Contact from './../pages/Contact';

export default class Navigation extends React.Component {
  render() {
    return (
      <Router>
        <div className="navigation">

          <nav>
            <Link to="/">Home</Link>
            <Link to="/about">About</Link>
            <Link to="/contact">Contact</Link>
          </nav>

{/*
  Below should be repositioned outside of <header>, in Stage component
*/}
          <div className="stage">
            <Switch>
              <Route exact path="/" component={Home} />
              <Route path="/about" component={About} />
              <Route path="/contact" component={Contact} />
            </Switch>
          </div>

        </div>
      </Router>
    )
  }
}

My question is: How can I have the Router render the required /page/ Components inside my <Stage> component, when selected from the <Navigation> component.

Since all the reacttraining.com examples are single-page, I'm struggling to determine if I'm making a logic mistake in assuming how my app should be optimally constructed, or a programming error in recreating a relation between the two elements with react-router v4.

Upvotes: 2

Views: 2373

Answers (1)

knowbody
knowbody

Reputation: 8276

All you need to do is to separate these two divs as you are wrapping stage inside the header. And as the Component needs to be rendered in a single element you need another div around the whole content:

export default class Navigation extends React.Component {
  render() {
    return (
      <Router>
        <div>
          <div className="navigation">
            <nav>
              <Link to="/">Home</Link>
              <Link to="/about">About</Link>
              <Link to="/contact">Contact</Link>
            </nav>
          </div>

          <div className="stage">
            <Switch>
              <Route exact path="/" component={Home} />
              <Route path="/about" component={About} />
              <Route path="/contact" component={Contact} />
            </Switch>
          </div>
        </div>
      </Router>
    );
  }
}

Update: Updating my answer:

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

const Header = () => <h1>I'm a header</h1>;

const Navigation = () => (
  <nav>
    <Link to="/">Home</Link>
    <Link to="/about">About</Link>
    <Link to="/contact">Contact</Link>
  </nav>
);

const Stage = () => (
  <div>
    <Route exact path="/" component={Home} />
    <Route path="/about" component={About} />
    <Route path="/contact" component={Contact} />
  </div>
);

const Footer = () => <h6>Footer</h6>;

const Home = () => <h3>Home</h3>;
const About = () => <h3>About</h3>;
const Contact = () => <h3>Contact</h3>;

const App = () => (
  <Router>
    <div>
      <Header />
      <Navigation />
      <Stage />
      <Footer />
    </div>
  </Router>
);

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

And here is the working version: https://codesandbox.io/s/v21BD37NX

Upvotes: 6

Related Questions