React Router: Redirect with Higher-Order Component

 by Robin Wieruch
 - Edit this Post

When using React Router in React, one can use the Navigate component to navigate a user away from a page in case of a certain condition. For example, the following example does not if there is no data, but redirects a user to the home page instead:

import { Navigate } from 'react-router-dom';
const List = ({ data }) => {
if (!data.length) {
return <Navigate replace to='/home' />;
}
return (
<ul>
{data.map((item) => {
return <li key={item}>{item}</li>;
})}
</ul>
);
};
export default List;

In this case the redirect is well placed. However, if there is much logic happening before of the conditional, e.g. by using (because they cannot be after a conditional rendering except with this ), then the logic has to execute even though there may be a redirect.

import { Navigate } from 'react-router-dom';
const List = ({ data }) => {
// lots of hooks here
// which is bad, because they execute
// even though there may be a redirect
// and all the hooks logic may not be used after all
if (!data.length) {
return <Navigate replace to='/home' />;
}
return (
<ul>
{data.map((item) => {
return <li key={item}>{item}</li>;
})}
</ul>
);
};
export default List;

Therefore, you can use a (HOC) for the redirect, because when wrapping the component into a HOC, the logic of the HOC would occur before the hooks from the wrapped component:

import { withRedirectIfBlank } from './withRedirect'
const List = ({ data }) => {
// lots of hooks here
return (
<ul>
{data.map((item) => {
return <li key={item}>{item}</li>;
})}
</ul>
);
};
export default withRedirectIfBlank({
redirectCondition: (props) => !props.data.length,
redirectTo: '/home',
})(List);

The HOC implementation could look like the following then:

import { Navigate } from 'react-router-dom';
const withRedirectIfBlank = (config) => (Component) => (props) => {
const { redirectCondition, redirectTo } = config;
if (redirectCondition(props)) {
return <Navigate replace to={redirectTo} />;
}
return <Component {...props} />;
};
export { withRedirectIfBlank };

Higher-Order Components are still useful these days, even though many React developers take them as legacy, because they are from a time when where used. Especially when they are used to render conditional JSX. However, if not using any conditional JSX, is often a better design choice in modern React.

Keep reading about 

So far, you've used broad authorization rules that check user authentication, where the dedicated authorization higher-order component redirects them to the login page if the user is not authenticated…

The Road to React

Learn React by building real world applications. No setup configuration. No tooling. Plain React in 200+ pages of learning material. Learn React like 50.000+ readers.

Get it on Amazon.