
No mucho después de que comencé a trabajar en mi puesto actual, el equipo se dio cuenta de que sería necesario actualizarnos a React 16 para poder usar una nueva biblioteca de IU que estábamos interesados en adoptar.
Para averiguar cuánto tiempo requeriría esta actualización, revisamos todos nuestros paquetes actuales para ver si eran compatibles con React 16 y para ver si todavía estábamos usando paquetes obsoletos o no admitidos.
Los inicios de nuestra base de código habían sido creados por desarrolladores que usaban cualquier biblioteca de código abierto o de terceros que quisieran, sin examinarlos realmente. Por lo tanto, descubrimos que muchos de los paquetes estaban obsoletos y debían reemplazarse lo antes posible.
Una de las mayores sorpresas para nosotros fue la desaprobación de react-router-redux
. Estábamos usando react-router-redux
junto con react-router v3. Esto nos llevó a pensar críticamente acerca de por qué estábamos usando redux
nuestro enrutador en primer lugar.
Una vez que comenzamos a buscar en el enrutador react v4, nos dimos cuenta de que las nuevas funciones eliminarían prácticamente cualquier motivo para que usemos una biblioteca adicional para conectar nuestro enrutador y redux
. Entonces, eso nos dejó en la posición de actualizar del enrutador react 3 al 4 y eliminarlo react-router-redux
de nuestra aplicación.
Entonces, tuve la tarea de actualizar nuestro enrutador a v4 después de estar en el puesto y trabajar con React durante aproximadamente 2 meses. Esto se debía a que la actualización de React Router 3 a React Router 4 parecía una tarea trivial. Pero, como descubrí rápidamente, fue un poco más complicado de lo que esperaba.
Al revisar la documentación, el repositorio de GitHub y muchas, muchas respuestas de Stack Overflow, finalmente reuní los pasos para la actualización y quise compartir mis hallazgos, especialmente para explicar cómo y por qué se realizan ciertos cambios.
El mayor cambio a tener en cuenta, de los creadores de React Router, es que la actualización de React Router 3 a React Router 4 es más que solo actualizar algunas bibliotecas y características: le permite cambiar fundamentalmente cómo funciona su enrutador. Los creadores de React Router querían volver a un enrutador simple, permitiendo al desarrollador personalizarlo como quisieran.
He dividido esta guía en 5 partes diferentes:
- Paquete
- Historia
- Ruta
- Accesorios
- Integración Redux
Paquete
La estructura del paquete React Router v4 cambió de tal manera que ya no es necesario instalar react-router; tiene que instalar react-router-dom
(y desinstalar react-router
), pero no pierde nada ya que reexporta todas react-router
las exportaciones. Esto significa que también debe actualizar las react-router
declaraciones de importación a react-router-dom
.
Historia
La historia es una parte esencial del enrutamiento, lo que nos permite recordar de dónde venimos y dónde nos encontramos actualmente. La historia se presenta de muchas formas para react-router, y podría llevar un tiempo explicarla. Entonces, para mantener este artículo sobre el tema, simplemente le recomendaré que lea este artículo que explica el historial en relación con el enrutador react 4. Este artículo debería cubrir la mayoría de los casos de su uso del historial.
Ruta
React Router v3 nos permitió colocar todas las rutas de nuestra aplicación en un archivo, al que llamaremos router.js. Sin embargo, React Router v4 le permite colocar rutas en los componentes que están renderizando. La idea aquí es enrutar dinámicamente la aplicación; en otras palabras, el enrutamiento tiene lugar mientras la aplicación se está procesando.
Sin embargo, si tiene una base de código heredada de tamaño decente con la que está trabajando, probablemente no hará un cambio tan grande. Afortunadamente, React Router v4 aún te permite colocar todas las rutas en un archivo central, que es como crearé todos nuestros ejemplos. Sin embargo, hay algunos componentes y funciones más antiguos que deberán reemplazarse.
IndexRoute
Anteriormente, IndexRoute
se usaba como ruta para alguna interfaz de usuario predeterminada de una ruta principal. Pero, en v4, IndexRoute
ya no se usa, ya que esta funcionalidad ahora está disponible en Route.
Para proporcionar una interfaz de usuario predeterminada, varias rutas que tienen la misma ruta permitirán que todos los componentes asociados se representen:
import { BrowserRouter as Router, Route } from 'react-router-dom'; // example of our route components
Por lo tanto, todos los componentes - Home
, About
y Contact
- rendirá. Debido a esto, tampoco puede anidar rutas.
Además, para permitir una mejor coincidencia sin el uso de IndexRoute
, puede usar la palabra clave exacta.
import { BrowserRouter as Router, Route } from 'react-router-dom'; // example of our route components
Enrutamiento exclusivo
Después de agregar la palabra clave exacta, “something.com/about”
se enrutará cuando el enrutador vea una ruta “/about”
. Pero ahora, ¿y si tienes otro camino “/about/team”
? Como dije antes, el enrutador renderizará cualquier cosa que coincida. Entonces, los componentes asociados con ambos “/about”
y “/about/team”
se renderizarán. Si eso es lo que pretendías, ¡genial! Sin embargo, si esto no es lo que desea, es posible que deba colocar un interruptor alrededor de este grupo de rutas. Esto permitirá que se procese la primera ruta que coincida con la URL.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
Tenga en cuenta que la palabra clave exacta todavía tiene que aparecer para el componente Inicio; de lo contrario, coincidiría con las rutas posteriores. También tenga en cuenta que tenemos que listar “/about/team”
antes “/about”
para que la ruta vaya al Team
componente en lugar del About
componente cuando lo vea “something.com/about/team”
. Si viera “/about”
primero, se detendría allí y renderizaría el About
componente porque Switch solo renderiza el primer componente que coincide.
Ruta por defecto
Una ruta predeterminada, o una ruta "atrapar todo", comúnmente utilizada para páginas 404, es la ruta que usa cuando ninguna de las rutas coincide.
En React Router v3, el valor predeterminado Route
era:
En React Router v4, el valor predeterminado Route
se cambió a:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; // this is our default route
When you don’t include a path in a Route
, the component will always render. So, as we discussed above, we can use Switch
to get only one component to render, and then place the “catch all” route very last (so it doesn’t use that one before the Router
gets a chance to check the rest of the paths), so something will always render even if the other paths don’t match.
onEnter
Previously, you could use onEnter
to make sure the component of the Route
has all of the information it needs or as a check (such as to make sure the user is authenticated) before the component rendered.
This feature has been deprecated because the new structure of Routes is that they should act like components, so you should take advantage of component lifecycle methods instead.
In React Router v3:
Becomes:
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
... componentDidMount() { this.props.fetchInfo(); } ...
Props
In React Router v4, the props passed through the router have changed, as did the way they are accessed. The Route now passes three props:
history
location
match
history
history
contains a lot of other properties and methods, so I won’t list all of them, but here is a selection that might be most commonly used:
length
: number of entries in the history stacklocation
: contains the same information as belowpush(path, [state])
: pushes new entry on history stackgoBack()
: allows you to move the pointer on the history stack back 1 entry
It’s important to note that history
is mutable, and while it contains a location
property, this instance of location
shouldn’t be used since it could have been changed. Instead, you want to use the actual location
prop discussed below.
location
The location has properties:
pathname
search
hash
state
location.search
is used to replace location.query
and it must be parsed. I used URLSearchParams
to parse it. So a URL such as “//something.com/about?string=’hello’”
would be parsed as such:
... const query = new URLSearchParams(this.props.location.search) const string = query.get('string') // string = 'hello' ...
Additionally, the state
property can be used to pass the location
-specific state
of components through props. So, if you wanted to pass some information from one component to another, you could use it like this:
... // To link to another component, we could do this: // However, if we wanted to add state to the location, we could do this: const location = { pathname: '/path/', state: { fromDashboard: true }, } ...
So, once we get to the component rendered by that path, we’ll have access to fromDashboard
from location.state.fromDashboard
.
match
match
has the following properties:
params
: gets the dynamic segments of the path from the URL — for example if the path is“/about/:id”
, in the component, accessingthis.props.match.params
will give you the id in the URLisExact
: true if the entire URL was matchedpath
: the path in the routes that was matchedurl
: the matched portion of the URL
Redux Integration
As I addressed earlier, we found that in our case, we didn’t need to have an additional library to connect redux
with our router, especially since our main use case for this — Blocked Updates — was covered by react router.
Blocked Updates
In some cases, the app doesn’t update when the location changes. This is called a “Blocked Update”. This can happen if both of these conditions are met:
- The component is connected to Redux via
connect()(Component)
. - The component isn’t rendered by a
In these cases, I wrapped the component’s connect with withRouter
.
This allowed the router information to follow the component when it gets linked to, so the app still updates when the Redux state changes.
And that’s it!
This upgrade took me over a week — a few days of trying to figure out how to do it at all, and then another few days to start actually making changes. Upgrading to React Router 4 is a huge change not to be taken lightly, but it’ll make your router a lot more lightweight and easy to use.
Please don’t hesitate to comment/ask questions!