Amir
Amir

Reputation: 192

React router with different templates for different routes v. 5

Hi I have seen this question and this is exactly what i am looking for but i can't get it to work. React Router V4 Routers with Master Pages / Templates

I am using version 5.2

App component includes the navigation and wraps two paths with two template components, 'Public' and 'Private' and when i click each link i expect that page to be wrapped by it's template but instead only the first link works and shows the template. The second link only changes the url in the browser address bar and only the content of first template remains on the page and the content of the second page doesn't show. If i change the order of the links always only the top link gets the correct template.

This is where i define the routes and links to them.

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <ul><li><Link to="/">Home</Link></li>
            <li><Link to="/members">Members</Link></li>
          </ul>
        </div>
        <Switch>
          <Public>
            <Route exact path="/"><Home /></Route>
          </Public>
          <Private>
            <Route path="/members"><Members /></Route>
          </Private>
        </Switch>
      </Router>
    );
  }
}
export default App;

My private and public templates are the same except for the titles one say private and the other public.

class Private extends Component {
  render() {
    return (
      <div className="container">
        <div className="row">
          <div className="col-md-2"><h2>PRIVATE</h2></div>
          <div className="col-md-8">{this.props.children}</div>
          <div className="col-md-2"></div>
        </div>
      </div>
    );
  }
}

export default Private;

I have been looking for something like this for a while as it looks like a potentially neat solution. If anyone knows how to fix this i would really appreciate it. Thanks

Upvotes: 0

Views: 1282

Answers (1)

Taghi Khavari
Taghi Khavari

Reputation: 6582

Here is what Switch Component does:

          React.Children.forEach(this.props.children, child => {
            if (match == null && React.isValidElement(child)) {
              element = child;

              const path = child.props.path || child.props.from;

              match = path
                ? matchPath(location.pathname, { ...child.props, path })
                : context.match;
            }
          });

as you see the Switch component only cares about the first level of its children and looks for a prop called path or from in that. if it doesn't find it it assumes that every path will match. so it always shows the first children no matter what.

what you need to do is change the order of the children like this:

<Switch>
  <Route exact path="/">
    <Public>
      <Home />
    </Public>
  </Route>
  <Route path="/members">
    <Private>
      <Members />
    </Private>
  </Route>
</Switch>

Upvotes: 1

Related Questions