Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Putting wrapper components in react router switch

I need to create a layout that only applies to certain routes. However, when I use a Switch and separate the routes that need alternate layouts, if I try to visit a page that doesn't exist it just takes me to the layout with nothing inside of it. Here is the sample code.

<Switch>
    <Route exact path="/" component={SampleComponent} />
    <TokenLayout>
        <Route path="/some-random-component" component={SomeRandomComponent} />
    </TokenLayout>
    <Route path="*" component={NotFound} />
</Switch>

the NotFound component never renders, instead it renders the TokenLayout with no children.

Any suggestions on how to resolve this?

like image 277
Marco Chavez Avatar asked Dec 11 '25 04:12

Marco Chavez


1 Answers

Issue

The issue here is that the Switch component "Renders the first child <Route> or <Redirect> that matches the location." The official docs don't make it overtly clear that Route (and variations of) and Redirect are the only valid children of the Switch component. When a non-route or non-redirect component is hit, route matching stops and that component is returned and rendered. What happens next is that the nested route rendering SomeRandomComponent is inclusively matched just as if it would be by the router not inside a Switch.

Solution

Refactor the code to render the TokenLayout component inside the route.

Here are a few suggestions:

  • Create a wrapper component

      const TokenLayoutWrapper = props => (
        <TokenLayout>
          <SomeRandomComponent {...props} />
        </TokenLayout>
      );
    

    ...

      <Switch>
        <Route exact path="/" component={SampleComponent} />
        <Route path="/some-random-component" component={TokenLayoutWrapper} />
        <Route path="*" component={NotFound} />
      </Switch>
    
  • Create a Higher Order Component

      const withTokenLayout = Component => props => (
        <TokenLayout>
          <Component {...props} />
        </TokenLayout>
      );
    

    Decorate the SomeRandomComponent component export:

      export default withTokenLayout(SomeRandomComponent);
    

    ...

      <Switch>
        <Route exact path="/" component={SampleComponent} />
        <Route path="/some-random-component" component={SomeRandomComponent} />
        <Route path="*" component={NotFound} />
      </Switch>
    
  • Just wrap SomeRandomComponent in an inline function using the render prop, pass the route props through to SomeRandomComponent.

      <Switch>
        <Route exact path="/" component={SampleComponent} />
        <Route
          path="/some-random-component"
          render={props => (
            <TokenLayout>
              <SomeRandomComponent {...props} />
            </TokenLayout>
          )}
        />
        <Route path="*" component={NotFound} />
      </Switch>
    
like image 114
Drew Reese Avatar answered Dec 13 '25 22:12

Drew Reese