Connecting Components with a Router Using Higher-order Component

Learn how to receive the Router's props using a higher-order component and pass the props to the wrapped component whenever it renders.

We'll cover the following

a Each component used as a component prop in a Router element is automatically passed the router props history, location, and match. Sometimes, however, it’s useful to be able to access Router functionality in components that are not using a direct route—for example, to redirect to another page using history.push().

The withRouter higher-order component

React Router provides a withRouter higher-order component to allow for such use cases. Each component wrapped by this higher-order component will automatically receive the Router element’s props, even though they are not used as a Route component:

withRouter(MyComponent);

The withRouter component is sometimes used in another situation: to prevent “update blocking.” This used to be a necessary workaround before React Router 5.0.0. Since then, however, this problem has been solved and is no longer necessary. We will still outline the rationale behind why this was necessary in case we ever find ourselves working with older versions of React Router.

If a component has been implemented as a PureComponent or has been wrapped by a React.memo() call for optimization reasons, re-renders are suppressed if no props or state have changed. Because most Router components, such as NavLink, access data in the router via React context, a PureComponent or a component wrapped by React.memo() might not receive any information that its children need re-rendered.

In those types of situations, it is recommended to wrap these components with a withRouter() higher-order component. Whenever a change in the routing occurs and new props with a new location are passed to the respective component, a re-render will be triggered. This principle also applies to the state management library Redux. If a component is connected to the Redux store via the connect() function, the component will prohibit the re-rendering of router-specific logic unless something has also changed in the store.

To avoid such cases, we wrap these components with a withRouter() higher-order component:

withRouter(connect()(MyComponent));

Since the release of React 16.3.0 and React Router 5.0.0, however, this issue has been solved, and you will only come across it while working with previous versions of these two libraries.

Get hands-on with 1200+ tech skills courses.