Table of Contents
React Router is a widely used routing library for React applications due to its API, which simplifies integration. The latest version of React-router (v6) was released in November 2021 and marked a significant API change. Version 5 of React-router was released in March 2019, but it faced some problems with its routing algorithm and configuration defaults. In version 6, React hooks are the driving force behind the new release, resulting in more efficient and compact code.
The article discusses the major problems with version 5, as well as changes to routing logic, bundle size reduction, route protection, and redirection, new features for forms in version 6.4, and also the features that are no longer available in the new version.
Smarter Routing
One of the significant upgrades React Router v6 brings is the new routing system. Which now uses a <Routes> component instead of <Switch>, and it lets relative routing, nested routes, and layouts, and does not use any more ‘exact’ prop which is used in version 5 to match the requested routes which share similar pathways and optional arguments.
Without using the “exact” prop in version 5, the code above would render the Products component in the ProductDetail. We might change this behavior by rearranging the code in this manner:
<Switch>
<Route path="/products/:productId" component={ProductDetail} />
<Route path="/products" component={Products} />
</Switch>
Since React Router 5’s routing algorithm struggles to match pathways by adjusting the order of the routes or adding an “exact” prop, React Router 6 simplifies it by using the Routes component and element prop to render the components, and now the order of the routes doesn’t matter anymore.
The management of nested routes is another new feature of version 6. The nested routes now should be wrapped in the Routes component, and there is no longer a need to include the parent’s route in the nested route’s path. You might also choose a different strategy in place of defining your routes in the component where you wish to load the content of the nested route. Your nested routes can be specified inside the parent component.
The information can then be displayed by telling the React-router where to render it using the Outlet component.
Determining the app’s routes with the useRoutes hook is a new routing API in React Router 6. Instead of using React components to specify and compose your app’s routes, you can use JavaScript objects. It accepts an array of JavaScript objects that are nested one within the other, each of which represents a route containing a path, an element, and optionally children. For example, Version 5 needs the use of a distinct package called react-router-config, which has now been included in the core of Version 6. Using the useRoutes hook makes defining routes easier and provides for greater readability and organization.
Reduced bundle and code size
The author points out that React Router v5’s most recent stable release (v5.3.4) has a bundle size that is four times more than React which can cause difficulties in compiling and deploying apps. In contrast, the latest version of React Router, v6, has a smaller bundle size with a 70% reduction, resulting in faster app loading, particularly over slow network connections.
Route protection and navigation
React Router v6 has introduced some significant changes in terms of route direction and navigation. In previous versions, route direction was managed through a combination of the “history” and “match” props passed down to components. However, in v6, the new “useNavigate” hook has been introduced, which allows for more direct and explicit navigation. This hook replaces the “history.push” and “history.replace” methods and provides a simple way to navigate to a new URL, without requiring access to the history object.
Moreover, in suspense-enabled apps, using the history instance directly could lead to bugs, so the navigate function is now aware of the app’s suspending state. Michael Jackson gives an example of it: if a user clicks on a link that suspends while loading data and then immediately clicks on another link to navigate to a different page, any push navigation that occurs at that time is automatically transformed into a replace action, removing the first navigation from the browser history. This feature can be useful in a single-page app with multiple links.
In addition to that, now we have access to the navigate function through the useNavigate hook, which allows us to navigate to any page. The go, goBack, and goForward methods that were available in the useHistory hook can be substituted with the navigate function, like so:
const handleClick = () => {
navigate('/home', { replace: true });
}
navigate(-1) // v5's history.go(-1) or history.goBack()
navigate(1) // v5's history.go(1) or history.goForward()
navigate(2) // v5's history.go(2)
In React Router v6, the Redirect component has been renamed to Navigate. According to Michael Jackson, redirects are usually used when you want to maintain an existing link but send all traffic intended for that location to a new URL to avoid broken links. In previous versions (v4/5), the naming “redirect” caused confusion among developers because it wasn’t actually redirecting. Therefore, the Redirect component has been renamed to Navigate in v6.
An example of how to use Navigate component is the following way:
<Navigate to="/dashboard" replace={true} state={from: location}/>
React Router v6 still allows the use of the familiar Link and NavLink components. The styling of NavLink can now be accomplished using a function that takes a destructured argument, {isActive}, instead of the previous method of using the activeClassName and activeStyle props. This change provides more flexibility and control to developers when styling active links.
In React Router, protected routes are routes that require authentication or authorization to access. Protected routes are commonly used in applications that require users to log in to access certain pages or features. In React Router v6, creating protected routes is straightforward. Developers can use the Route component and a custom function to check whether the user is authenticated. If the user is not authenticated, the protected route can redirect the user to a login page or display an error message. Protected routes can help ensure that sensitive data and functionality are only accessible to authorized users, improving the security of the application.
New features of Forms in React Router 6.4
Additionally, I want to highlight the latest additions in React Router 6.4 that simplify the process of data fetching and submission. These changes have significantly reduced the amount of code required to handle data fetches. As stated in an Academind video, a drawback of fetching data after the component is loaded, rather than during navigation to the component, is that it can create disadvantages. Furthermore, with the new features, we are no longer required to manually manage error and loading states, which is another advantage.
A newly added “loader” prop in the Route component can now be used to assign an API call to our components. The useLoaderData hook from react-router-dom can then be used to obtain the data required for rendering. However, it is not possible to use Browser Router for this functionality, and instead, the app’s router list must be created using createBrowserRouter, as shown in the provided code.
This modification in react-router allows for the automatic handling of data fetching. This means that there is no need to manually fetch data using useEffect, or manage any loading state. Instead, the page is loaded after the data has been fetched, resulting in much less code to write. This is evident in the image below:
In addition, we can avoid manually monitoring the error state by using the errorElement prop in our routes that involve data fetching. Similar to the element prop, we can define a component or JSX code to display if an error occurs, rather than tracking the error state ourselves. Moreover, the use of the useRouteError hook allows access to additional error messages defined by the API call.
With the new Form component in React-router v6, submitting data is also easy. It eliminates the need to manually handle states such as isSubmitting and errors. This component allows for setting the method (get, put, etc.) and action, which defines the path to which the request should be sent. An action function can then be exported and registered in the Route component by setting the action prop.
What was removed from React Router v6?
React Router 6 does not support props such as match, location, and history. Certain features have been removed from version 6 due to ambiguity or faults, such as usePrompt and useBlocker, which were used to confirm or prevent users from leaving a page. There is hope that these features will be added in future editions. In the meantime, you can use third-party libraries like react-router-prompt.
Conclusion
In conclusion, the release of version 6 of the React Router library brought significant changes and improvements, mainly due to the implementation of React hooks. The new version offers more compact and efficient code, better routing logic, reduced bundle size, enhanced route protection and redirection, and new features for forms. While some features were removed in this version (usePrompt, history, Switch, etc.), the overall changes and improvements make this release a significant update for React developers using the React Router library. It is highly recommended to update your React Router to the ultimate version. If the app’s routing system is complicated and relies on outdated v5 features, the official incremental migration guide is available to aid in the transition.
Interested in staying up-to-date with the latest technologies in frontend development? I suggest you keep an eye on Apiumhub‘s blog. New and interesting content gets published every week.
Author
-
Graduated from Istanbul Technical University with a bachelor degree of computer engineering in June 2018. During her studies, she has been involved in projects in various areas including web development, computer vision and computer networks.
View all posts