Fecha publicación: 10 nov 2021

Migrando de React Router 5 a la versión 6

Hace no mucho que salió la nueva versión de React Router (la 6), como es un cambio de versión mayor contiene "breaking changes". En este video vamos a migrar una aplicación simple que usa TypeScript y React Router 5.1 a la versión 6.

Manos a la obra

El proyecto

En este proyecto de ejemplo, tenemos una aplicación sencilla, con tres páginas:

  • Una de lógin, en la que navegamos de forma programática usando useHistory
  • Otra de listado, en la que navegamos usando un Link.
  • Otra de detalle, que ofrece la opción de volver a la página de login navegando de forma programática (utilizando useHistory)

Instalando

Lo primero que vamos a hacer es desinstalar la versión 5 y sus typings e instalar la versión 6

Vamos a desinstalar react-router-dom:

npm uninstall react-router-dom --save-dev

Y a desinstalar los typings:

npm uninstall @types/react-router-dom --save-dev

Vamos a instalar la nueva versión:

npm install react-router-dom --save

Si te fijas, ya no nos hace falta instalar lo typings aparte, vienen incluidos con la librería.

Rutas y useHistory

Pasamos a adaptar el código para que soporte la nueva definición de rutas y la navegación.

Si ahora hacemos un npm start, podemos ver que el proyecto rompe

Primer error switch ya no existe en la versión 6

Toca arreglar esto:

Lo primero switch ya no se usa, en vez de eso tenemos el componente Routes (en plural), podemos actualizar lo que importamos de react-router-dom en nuestro fichero de aplicación.

./src/app.tsx

import React from "react";
- import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
+ import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

Y en la definición de rutas, realizamos el cambio.

./src/app.tsx

     <Router>
-      <Switch>
+      <Routes>
        <Route exact path="/">
          <LoginPage />
        </Route>
        <Route path="/list">
          <ListPage />
        </Route>
        <Route path="/detail">
          <DetailPage />
        </Route>
+      </Routes>
-      </Switch>
     </Router>

También se nos marca en rojo el tag exact, ya no nos hace falta usarlo. en la versión 6 de React lo han eliminado, ya que han mejorado la detección de rutas, y entre otras mejoras ya no afecta el orden en el que escribas las mismas.

-  <Route exact path="/">
+  <Route path="/">
    <LoginPage />
  </Route>

Si seguimos traspilando, podemos ver que tampoco le gusta a react-router-dom el hook useHistory, en la versión 6 tenemos que usar useNavigate

Vamos a cambiar esto en la página de login

./src/login.tsx

import React from "react";
- import { Link, useHistory } from "react-router-dom";
+ import { Link, useNavigate } from "react-router-dom";


export const LoginPage: React.FC = () => {
-  const history = useHistory();
+  const navigate = useNavigate();


  const handleNavigation = () => {
-    history.push("/list");
+    navigate("/list");
  };

Y en la de detalle:

import React from "react";
- import { Link, useHistory } from "react-router-dom";
+ import { Link, useNavigate } from "react-router-dom";


export const DetailPage: React.FC = () => {
-  const history = useHistory();
+  const navigate = useNavigate();


  const handleNavigation = () => {
-    history.push("/list");
+    navigate("/list);
  };

  return (
    <>
      <h2>Hello from Detail page</h2>
      <button onClick={handleNavigation}>Login</button>
    </>
  );
};

Si arrancamos la aplicación, vemos que todo está en blanco y al ver la consola nos sale el siguiente error:

Uncaught Error: [LoginPage] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>

¿Qué está pasando aquí? Que ya no vale poner como componente hijo de Route el contenido de cada página, tenemos que usar la propiedad element

./src/app.tsx

export const App = () => {
  return (
    <Router>
      <Routes>
-       <Route path="/">
+       <Route path="/" element={<LoginPage/>}/>
-          <LoginPage />
-        </Route>
-        <Route path="/list">
+        <Route path="/list" element={<ListPage/>}/>
-          <ListPage />
-        </Route>
-        <Route path="/detail">
+        <Route path="/detail" element={<Detail/>}/>
-          <DetailPage />
-        </Route>
      </Routes>
    </Router>
  );
};

Con estos cambios ya podemos ver que vuelve a funcionar la aplicación.

¿Te apuntas a nuestro máster?

Si te ha gustado este ejemplo y tienes ganas de aprender Front End guiado por un grupo de profesionales ¿Por qué no te apuntas a nuestro Máster Front End Online Lemoncode? Tenemos tanto edición de convocatoria con clases en vivo, como edición continua con mentorización, para que puedas ir a tu ritmo y aprender mucho.