Question: Nested routes with react router v4

Question

Nested routes with react router v4

Answers 1
Added at 2017-01-04 23:01
Tags
Question

I am currently struggling with nesting routes using react router v4.

The closest example was the route config in the React-Router v4 Documentation.

I want to split my app in 2 different parts.

A frontend and an admin area.

I was thinking about something like this:

<Match pattern="/" component={Frontpage}>
  <Match pattern="/home" component={HomePage} />
  <Match pattern="/about" component={AboutPage} />
</Match>
<Match pattern="/admin" component={Backend}>
  <Match pattern="/home" component={Dashboard} />
  <Match pattern="/users" component={UserPage} />
</Match>
<Miss component={NotFoundPage} />

The frontend has a different layout and style than the admin area. So within the frontpage the route home, about and so one should be the child routes.

/home should be rendered into the Frontpage component and /admin/home should be rendered within the Backend component.

I tried some variations but I always ended in not hitting /home or /admin/home.

Update

With the solution from @azium I managed to get it work with the following code:

cont Frontend = () => {
    return (
        <div>
          <h2>Frontend</h2>
          <ul>
            <li><Link to={`${pathname}`}>Home</Link></li>
            <li><Link to={`${pathname}/about`}>About</Link></li>
            <li><Link to={`${pathname}/error`}>Not found</Link></li>
          </ul>
          <Match pattern={`${pathname}`} exactly component={HomePage} />
          <Match pattern={`${pathname}/clan`} component={AboutPage} />
          <Miss component={NotFoundPage} />
        </div>
    );
}

const Backend = () => {
    return (
        <div>
          <h2>Backend</h2>
          <ul>
            <li><Link to={`${pathname}`}>Dashboard</Link></li>          
            <li><Link to={`${pathname}/error`}>Not found</Link></li>
          </ul>
          <Match pattern={`${pathname}`} exactly component={Dashboard} />
          <Miss component={NotFoundPage} />
        </div>
    );
}

<Match
    pattern="/" exactly render={() => (
      <Redirect to="/frontend" />
    )}
/>
<Match pattern="/frontend" component={Frontend} />
<Match pattern="/backend" component={Backend} />
<Miss component={NotFoundPage} />

I added a redirect to frontend when someone is hitting the root path so I don't have to wrap my components with a frontpage component all the time.

Answers to

Nested routes with react router v4

nr: #1 dodano: 2017-01-04 23:01

I think you want something along these lines:

UPDATE: okay I actually tried this out and I was wrong about some of my assumptions.

My old answer:

let App = props =>
  <div>
    <Match exactly pattern="/" component={FrontPage} />
    <Match pattern="/admin" component={Backend}/>
    <Miss component={NotFoundPage} />
  </div>

let FrontPage = ({ pathname }) =>
  <div className="cool-frontpage-stuff">
    <Match pattern={`${pathname}/home`} component={HomePage} />
    <Match pattern={`${pathname}/about`} component={AboutPage} />
  </div>

let Backend = ({ pathname }) =>
  <div className="cool-backend-stuff">
    <Match pattern={`${pathname}/home`} component={Dashboard} />
    <Match pattern={`${pathname}/users`} component={UserPage} />
  </div>

The not quite correct answer: (also thanks to @Paul S for the tip about exactly

let App = props =>
  <div>
    <Match 
      // don't put exactly 
      pattern="/" 
      component={FrontPage} 
    />
    <Match pattern="/admin" component={Backend}/>
    <Miss component={NotFoundPage} />
  </div>

// `pathname` here will just be `/` so I had an extra `/`
let FrontPage = ({ pathname }) =>
  <div className="cool-frontpage-stuff">
    <Match pattern={`${pathname}home`} component={HomePage} />
    <Match pattern={`${pathname}about`} component={AboutPage} />
  </div>

// this part was correct
let Backend = ({ pathname }) =>
  <div className="cool-backend-stuff">
    <Match pattern={`${pathname}/home`} component={Dashboard} />
    <Match pattern={`${pathname}/users`} component={UserPage} />
  </div>

So because I removed exactly, /admin will also match /, showing both components.

Refactorin' time:

let App = props =>
  <div>
    <Match pattern="/home" component={HomePage} />
    <Match pattern="/about" component={AboutPage} />
    <Match pattern="/admin" component={Backend}/>
    <Miss component={NotFoundPage} />
  </div>

// just pass children here instead of matching routes (not a page, a layout)
let FrontLayout = ({ children }) =>
  <div className="cool-frontpage-stuff">
    {children}
  </div>

let HomePage = props => <FrontLayout>Homepage!</FrontLayout>
let AboutPage = props => <FrontLayout>About!</FrontLayout>

// this part was correct
let Backend = ({ pathname }) =>
  <div className="cool-backend-stuff">
    <Match pattern={`${pathname}/home`} component={Dashboard} />
    <Match pattern={`${pathname}/users`} component={UserPage} />
  </div>
Source Show
◀ Wstecz