React Router - How to hide components on 404 page

Viewed 1070

I am building an application using react and using react router to manage the routing. I am currently handling the 404 error. My problem is that my application is displaying my navbar and subfooter and footer when at the 404 page i created is displayed. whats the best way to hide these 3 components?

my app.js currently looks like this..

class App extends Component {
  
  render() {
    return (
      <div className="body">
      <div className="App">
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route exact path="/" component={Home} exact={true} />
            <Route exact path="/projects" component={Projects} />
            <Route component={PageNotFound}/>
            <Redirect to="/404" /> 
          </Switch>
          <SubFooter/>
          <Footer />
        </BrowserRouter>
      </div>
      </div>
    );
  }
}
2 Answers

you need to create a main route which contain a route for main app (contain nav + contents routes +footer) and a route for 404 page:

const Main = () => (
  <BrowserRouter>
    <Switch>
      <Route path="/404" exact render={() => <div>404</div>} />
      <Route path="/" component={App} />
    </Switch>
  </BrowserRouter>
);

for app js :

import React from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <div>navbar</div>
      <div>footer</div>
      <Switch>
        <Route path="/" exact render={() => <div>home</div>} />
        <Route exact path="/projects" render={() => <div>projects</div>} />
        <Redirect to="/404" />
      </Switch>
    </div>
  );

full example here :example

note : you need to place 404 route before main app route to match first.

You can make a layout for error something like:

layout/Error404.js

  import React, { Suspense } from 'react';

  export const ErrorLayout = (props) => {
  const { children } = props;  

  return (
    <div>
      <div>
        <Suspense fallback={"loading..."}>
          {children}
        </Suspense>
      </div>
    </div>
  );
}
 

layout/publicLayout.js

  import React, { Suspense } from 'react';

  export const PublicLayout = (props) => {
  const { children } = props;  

  return (
    <div>
      <NavBar />
      <div>
        <Suspense fallback={"loading..."}>
          {children}
        </Suspense>
      </div>
      <SubFooter/>
      <Footer />
    </div>
  );
}
 

and create a custom route to render what you need for example:

routes/myErrorRoute.js

import React from "react";

export const ErrorRouteLayout = (props) => {
  const { layout: Layout, component: Component, ...rest } = props;

  return (
    <Route
      {...rest}
      render={(matchProps) =>
         Layout? (
          <Layout>
            <Component {...matchProps} />   
          </Layout>
        ) : (
          <Component {...matchProps} />
        )
      }
    />
  );
};
    

routes/publicRoute.js

import React from "react";

export const PublicRouteLayout = (props) => {
  const { layout: Layout, component: Component, ...rest } = props;

  return (
    <Route
      {...rest}
      render={(matchProps) =>
         Layout? (
          <Layout>
            <Component {...matchProps} />   
          </Layout>
        ) : (
          <Component {...matchProps} />
        )
      }
    />
  );
};

and finally, your app.js should look something like this

import { ErrorLayout  }  from './layout/Error404'
import { PublicLayout  }  from './layout/publicLayout'
import { ErrorRouteLayout   } from './routes/myErrorRoute'
import { PublicRouteLayout    } from './routes/publicRoute'


class App extends Component {
  
  render() {
    return (
      <div className="body">
      <div className="App">
        <BrowserRouter>
          <PublicRouteLayout 
            component={YourComponent}
            exact
            path="/home"
            layout={PublicLayout}
           />
          <ErrorRouteLayout 
            component={YourComponent}
            exact
            path="/error404"
            layout={ErrorLayout}
           />
            
            <Redirect to="/404" /> 
          </Switch>
        </BrowserRouter>
      </div>
      </div>
    );
  }
}
Related