1

In my react app I currently have this:

<Router>
    <div class Name="App">
      <Route path="/" exact component={PersonList} />
      <Route path="/rules" exact component={RulesPage} />
      <Route path="/roles" exact component={RolesPage} />
      <Route path="/test" exact component={Test} />
      <Footer />
    </div>
  </Router>

However I want the footer element to be hidden if the route path is "/test" It would be a lot cleaner than writing:

<Route path="/roles" exact component={Footer} />
<Route path="/rules" exact component={Footer} />
<Route path="/" exact component={Footer} />

If anyone knows the function to do this it would be greatly appreciated.

zifyl
  • 73
  • 5

4 Answers4

1

You could create a higher-order component that renders a component with a footer and then you could render that higher-order component at all the paths other than /test.

Higher-order component just takes a component that should be displayed with a Footer component and returns another component that just renders the wrapped component along with the Footer component.

function WithFooter(WrappedComponent) {
  const EnhancedComponent = (props) => {
    return (
      <>
        <WrappedComponent {...props} />
        <Footer />
      </>
    );
  };

  return EnhancedComponent;
}

After this, instead of exporting PersonList component, you need to export the component returned by calling WithFooter higher-order component as shown below:

function PersonList() {
  ...
}

export default WithFooter(PersonList);

You need to do the same for other components as well that should be rendered with a Footer.

With higher-order component all set-up, your routes definition don't need to change:

<Router>
   <Route path="/" exact component={PersonList)} />
   <Route path="/rules" exact component={RulesPage} />
   <Route path="/roles" exact component={RolesPage} />
   <Route path="/test" exact component={Test} />
</Router>

Alternative solution is to conditionally render the Footer component after checking the URL using window.location or useParams() hook provided by react-router-dom but useParams() will only work if your component is rendered using react router. In your case, you will need window.location.

Yousaf
  • 25,372
  • 4
  • 33
  • 58
  • `withFooter` is not defined – zifyl Oct 11 '20 at 16:20
  • 1
    you need to write `withFooter` higher-order component, its not a built-in component – Yousaf Oct 11 '20 at 16:21
  • In case you are not clear as to how you could implement the higher-order component and make it all work, I have added more details of how you could implement the higher-order component and other changes you need to do. – Yousaf Oct 11 '20 at 16:55
0

In your Footer component you could just check if the window.location.pathname includes /test and just return null

Agustin Moles
  • 1,256
  • 6
  • 14
  • ``` if(window.location.pathname.includes === "/test"){ return( null ) } ``` I added this, still shows up on the website – zifyl Oct 11 '20 at 16:18
0

Another option incase you are not familiar with the HOC pattern is to render the <Footer/> component inside only those components that need it rather than at the top level.

TheMonarch
  • 302
  • 2
  • 8
0

You can check for route details inside of the footer and render that based on your condition. React Router >= 5.1 ships with useRouteMatch if you're using hooks. If you're using classes instead (or an older react router), you'll need to use the withRouter High-Order Component. You can also check the window location yourself but I'd recommend using the tools that are already available to you through react router.

Example with hooks

function Footer() {
  const match = useRouteMatch("/test");

  // You can also use match.isExact when it's avaible to narrow
  // the check down to specifically "/test" but still keep urls
  // such as "/test/some/other/path"
  if (match /*&& match.isExact*/) return null;

  return <footer>This is the footer</footer>;
}

Example with the higher order component

class FooterWithRouter extends Component {
  render() {
    if (this.props.location.pathname === "/test") {
      return null;
    }

    return <footer>This is the footer</footer>;
  }
}
const Footer = withRouter(FooterWithRouter);

CodeSandbox for code samples https://codesandbox.io/s/runtime-cdn-v7icj

https://v7icj.csb.app/ https://v7icj.csb.app/test

Dennis Martinez
  • 5,946
  • 11
  • 48
  • 65
  • Using `useRouteMatch` hook will work but i wouldn't recommend it for two reasons: 1. `Footer` component shouldn't have to care at which route it is rendered or not rendered. 2. Everytime there's a new route at which `Footer` shouldn't render, you will need to update the `Footer` component. – Yousaf Oct 11 '20 at 17:16
  • @Yousaf fair points. One could argue that with the HOC, each component now indirectly cares about the footer and every new component that needs the footer needs to reference the HOC, causing more indirect relationships. As for the footer not being aware of the current route. Sure, but who's responsibility is it? The apps? If that's the case, hoist the logic up into the app and leave the footer alone. – Dennis Martinez Oct 11 '20 at 17:40