Actualizando a la última versión de React Router
Clase 46 de 58 • Curso Profesional de React con Redux 2016
Contenido del curso
Fundamentos
- 3

¿Qué es React?
05:12 min - 4

Hola Mundo con React
07:31 min - 5

¿Qué es y cómo funciona el Virtual DOM?
05:39 min - 6

Introducción a JSX
03:58 min - 7

Creación de componentes
13:21 min - 8

Componentes Puros vs de Estado
03:57 min - 9

Ciclo de vida de un componente
10:23 min - 10

Ciclo de vida de componentes
04:19 min - 11

Manejo de eventos del DOM
04:31 min - 12

Event handlers con parámetros personalizados
03:46 min - 13

Contexto de la aplicación
05:19 min - 14

Componentes de Alto Orden (HOC) y Mixins
08:22 min
Creación del proyecto
- 15

Presentación del proyecto
01:01 min - 16

Instalación de Node.js y usando npm
04:44 min - 17

Estructura de archivos
05:02 min - 18

Iniciar un servidor de render básico - Render en Server
03:40 min - 19

Module bundlers en JavaScript
06:02 min - 20

Configurar Webpack para el servidor de render
09:23 min - 21

Crear una app con React y React Router
04:21 min - 22

Manejo de rutas en el servidor con React Router
14:45 min - 23

Crear cliente para consumir el API
05:04 min - 24

Iniciar la app en el navegador y configurar Webpack para producción
08:58 min - 25

Iniciar un servidor de estáticos con zeit/list
04:33 min - 26

Herramientas de desarrollo de React
03:22 min - 27

Consumir el API y mostrar datos en la home
10:16 min - 28

Perfil de usuarios
08:13 min - 29

Estado de cargando y detalle de post
07:46 min - 30

Paginación de posts mediante scroll infinito
06:42 min - 31

Mostrar listado de comentarios en cada post
02:56 min - 32

Estilizar componentes con CSS Modules
18:43 min - 33

Linter y buenas prácticas con ESLint
22:21 min - 34

Internacionalización con React Intl
17:57 min - 35

Deploy a producción
27:30 min
Implementación de Redux
- 36

Patrones de arquitectura de aplicaciones Frontend
05:35 min - 37

Implementación inicial con Redux para los posts
20:37 min - 38

Uso de middlewares
08:39 min - 39

Acciones asíncronas
09:11 min - 40

Dividir el reducer en funciones más pequeñas y combinarlas
12:16 min - 41

Datos inmutables con Immutable.js
14:00 min - 42

Herramientas de desarrollo
08:08 min - 43

Conclusiones
02:02 min - 44

Pruebas automatizadas de reducers
09:03 min - 45

Pruebas de componentes de React
10:33 min - 46

Actualizando a la última versión de React Router
Viendo ahora
Desafíos
Contenido bonus
- 51

Glosario
03:47 min - 52

Evitar que webpack genere el CSS durante el build del servidor
00:57 min - 53

LazyLoad de imágenes
08:07 min - 54

Animaciones con ReactCSSTransitionGroup
07:31 min - 55

Server render con Next.js
11:53 min - 56

Aplicaciones universales/isomórficas
02:04 min - 57

Iniciar proyectos con create-react-app
04:34 min - 58

Diplomado de desarrollo de aplicaciones con ReactJS
00:38 min
React Router actualizó su API pública, por eso es necesario que cambiemos como la forma en la que usamos esta librería. Para eso vamos a tomar el proyecto que hicimos y actualizarlo.
Lo primero que vamos a hacer es desinstalarlo con el comando:
npm rm -S react-router
Y luego vamos a instalar react-router-dom con el comando:
npm i -S react-router-dom@next
La razón de instalar react-router-dom y no react-router es que desde ahora React Router va a soportar una versión para aplicaciones web (-dom) tanto en el cliente como en el servidor y una versión para aplicaciones de React Native (-native). En nuestro caso nos vamos a concentrar en la versión para web.
Actualizando el servidor de render
Vamos a ir a source/server.jsx y vamos a dejar de importar react-router, en vez de eso vamos a importar:
import { StaticRouter } from 'react-router-dom';
Acá podemos ver el primer cambio, en vez de importar ServerRouter ahora importamos StaticRouter y ya no necesitamos createServerRenderContext. Luego de cambiar este import vamos cambiar la siguiente línea.
const context = createServerRenderContext();
Y vamos a colocar:
const context = {};
Como vemos es simplemente crear un objeto vacío en vez de ejecutar una función. Luego tenemos que modificar donde hacemos el renderToString para usar StaticRouter quedando algo así:
const html = renderToString( <Provider store={store}> <IntlProvider locale={locale} messages={messages[locale]}> <StaticRouter location={request.url} context={context}> <Pages /> </StaticRouter> </IntlProvider> </Provider>, );
De esta forma ya estamos haciendo el render con los nuevos componentes de React Router. Ahorat tenemos que eliminar la línea donde obteníamos el resultado del contexto.
const result = context.getResult();
Ya que el resultado va a estar directamente en el objecto context que creamos antes. De igual forma vamos a cambiar la validación de result.missed por context.url y vamos a usar este mismo context.url donde antes definíamos el Location al hacer redirect. Quedando algo similar a esto:
if (context.url) { response.writeHead(301, { Location: context.url, }); response.end(); }
Un último cambio es que React Router ya nos dice si no encontró la URL (un 404) por lo que tanto la condición como el doble render que había que hacer es innecesario y podemos eliminarlos.
Actualizando nuestras rutas
Lo siguiente que vamos a actualizar es el archivo source/pages/containers/Page.jsx. Al igual que antes vamos a cambiar la línea donde importamos React Router quedando así:
import { Route, Switch, } from 'react-router-dom';
Como vemos en vez de Match y Miss importamos Route y Switch. Luego en todos los lugares donde usábamos Match y Miss tenemos que usar Route quedando así:
{/* List de artículos */} <Route path="/" exact component={Home} /> {/* Detalle de artículo */} <Route path="/post/:id" exact component={Post} /> {/* Perfil de usuario */} <Route path="/user/:id" exact component={Profile} /> {/* Galería de fotos */} <Route path="/gallery" exact component={Gallery} /> {/* Error 404 */} <Route component={Error404} />
Como vemos el prop pattern ahora se llama path y exactly es exact. El resto de props es igual. Otra cosa que vamos a hacer es envolver todos estos componente en Switch.
Este componente Switch lo que hace es que una vez una de las rutas haga render deja de verificar las otras rutas de la aplicación. Sin usar este componente React Router verificaría cada ruta definidia y si más de un componente hacía match entonces renderizaba todos esos componentes (pudiendo ser N). Switch nos evita eso completamente, solo permitiendo una ruta.
El código de nuestro componente Page quedaría algo así al final:
function Pages() { return ( <main role="application"> <Header /> <Switch> {/* List de artículos */} <Route path="/" exact component={Home} /> {/* Detalle de artículo */} <Route path="/post/:id" exact component={Post} /> {/* Perfil de usuario */} <Route path="/user/:id" exact component={Profile} /> {/* Galería de fotos */} <Route path="/gallery" exact component={Gallery} /> {/* Error 404 */} <Route component={Error404} /> </Switch> </main> ); }
Importando el componente Link y BrowserRouter
Lo siguiente que vamos a hacer es muy simple, en todos los lugares donde importamos Link de React Router vamos a cambiar el import y vamos a usar la siguiente línea:
import { Link } from 'react-router-dom';
Simplemente es importar Link de react-router-dom. Luego vamos a ir a source/client.jsx y vamos a cambiar el import de BrowserRouter para importarlo de react-router-dom.
import { BrowserRouter } from 'react-router-dom';
Con esto ya cambiamos todos los imports necesarios y estamos usando los nuevos componentes de React Router. Hay un último cambio que hacer y es cambiar un dato dentro de dos de nuestras página.
Obteniendo parámetros de la URL
En los componentes source/pages/containers/Post.jsx y source/pages/containers/Profile.jsx obteníamos un prop llamado params que era un objeto con todos los parámetros de la URL, como por ejemplo el id del post o usuario cuyo detalle estábamos viendo. Ahora para poder acceder a este datos es necesario usar un prop llamado match que posee el objeto params.
Eso significa que ahora el initialFetch de Post.jsx va a hacer el fetch de la siguiente forma:
const [ post, comments, ] = await Promise.all([ api.posts.getSingle(this.props.match.params.id), api.posts.getComments(this.props.match.params.id), ]);
Y el initialFetch de Profile.jsx va a hacerlo así:
const [ user, posts, ] = await Promise.all([ api.users.getSingle(this.props.match.params.id), api.users.getPosts(this.props.match.params.id), ]);
Y a su vez el propTypes de ambos componentes va a ser el tener el siguiente:
match: PropTypes.shape({ params: PropTypes.shape({ id: PropTypes.string, }), }),
Conclusiones
Con esto ahora ya toda nuestra aplicación debería funcionar con la última versión de React Router sin problemas. Este tipo de casos donde una librería se actualice y cambio su API pública es algo común en el mundo de JavaScript y como desarrolladores es parte de nuestro trabajo mantenernos al tanto y actualizar nuestro código para estar al día con las últimas versiones.
No consideren esto como un problema o algo malo, sino como algo natural y hasta deseable, ya que significa que las librerías o frameworks que usemos están mejorando y evolucionando.