Lecciones del curso

Introducción al desarrollo web full stack con React Router

RRv7 como puente a React 19
5m
Todo sobre rutas
6m
Todas las piezas de un Route Module
7m
Cargando datos desde la base de datos
4m
Actions y mutaciones
7m
Componente <Link> y navegación
5m
UI Patterns: Pending & Optimistic
4m
¿Cómo sustituir un useEffect?
3m
Tipado seguro de extremo a extremo
1m
Testing con RRv7
1m
Instalación
1m
Estrategias de renderizado
3m

<Link> y navegación en RRF

Hay muchas maneras de navegar en una aplicación construida con React Router Framework. Tenemos a los componentes <Link> y <NavLink> que son la mejor opción siempre que se pueda. Pero, como vimos en la lección pasada, el componente <Form> también detonará la navegación; no te olvides de esto, te será muy útil. Tenemos también al hook useNavigate, que es ya muy conocido dentro de la comunidad de React Router. Pero, también tendremos una herramienta del lado del servidor con la que podremos navegar: la función redirect. Veamos pues, cada una de estas opciones con más detalle ¿te late? 🧐

Comencemos con NavLink

El componente <NavLink> es casi lo mismo que el componente <Link> solo que este componente está pensado para reflejar estados de navegación. Esto, nos facilitará cambiar nuestra interfaz para representar los diferentes estados de la carga; mira, veamos un ejemplo. 🔬

import { NavLink } from "react-router"; export default function Route() { return ( <nav> <NavLink to="/" end> Inicio </NavLink> <NavLink to="/dashboard" end> Panel de control </NavLink> <NavLink to="/contactos">Toda la gente</NavLink> <NavLink to="/mi-perfil">Perfil</NavLink> </nav> ); }

El solo hecho de emplear este componente en vez de <Link> será suficiente para que las clases CSS se apliquen y cambien automáticamente. ¿Que cuáles clases CSS?

a.active { color: red; } a.pending { animate: pulse 1s infinite; } a.transitioning { /* css transition is running */ }

Pues estas tres. Este componente transicionará automáticamente entre las clases active, pending y transitioning. Solo añádelas a tus estilos CSS e invierte tu tiempo en decidir los bonitos colores que preferirás, en vez de estar peleándote con los ternarios en el JSX. 🤩 

Ahora, que si lo tuyo es JS y andar de peleonero(a) con los ternarios en el JSX, entonces, el <NavLink> también tiene algo para ti. 🥊

// className <NavLink to="/cursos" className={({ isActive, isPending, isTransitioning }) => [ isPending ? "pending" : "", isActive ? "active" : "", isTransitioning ? "transitioning" : "", ].join(" ") } > Todos los cursos </NavLink>

Podemos usar el callback que nos devuelve tres booleanos dentro de className y también dentro de styles ¡y hasta de children!

// style <NavLink to="/blog" style={({ isActive, isPending, isTransitioning }) => { return { fontWeight: isActive ? "bold" : "", color: isPending ? "red" : "black", viewTransitionName: isTransitioning ? "slide" : "", }; }} > Messages </NavLink> // children <NavLink to="/mis-videos"> {({ isActive, isPending, isTransitioning }) => ( <span className={isActive ? "active" : ""}> Mis videos </span> )} </NavLink>

Aquí hay para todos, para los que trabajan con bonitos estilo y para los mugrosos como “sho”, cómo de que no. 👨🏿‍🦳 👩🏼‍🦲👩🏼‍🎤 Pero si este componente es un overkill para tu caso de uso, y, solo necesitas navegar rapidito sin representar ningún estado ni estilos, entonces, el componente <Link> es lo que buscas. 🔦

El componete <Link>

<Link> es el componente que más usaremos para navegar dentro de nuestras aplicaciones React Router.

import { Link } from "react-router"; export default function Route() { return ( <> Te hemos enviado tu link mágico. 🧙‍♂️ <Link to="/">Volver al inicio</Link> </> ); }

Simple y bonito ¿apoco no?

👀 Toma en cuenta que <Link> está pensado para rutas internas de tu app, si necesitas un enlace externo, siempre podrías implementar el clásico anchor: <a href="https://www.easybits.cloud" rel="noreferrer" target="_blank" >.

El componente <Form>

Claro que se puede navegar con un <Form>. Hay una lectura que te quiero recomendar para que entiendas mejor el diseño original de la plataforma. Se llama: https://hypermedia.systems/. Si puedes, dátelo. 📖

Pero, mientras tanto, veamos un ejemplo super simple con <Form>.

<Form action="/blog"> <input type="text" name="search" /> <input type="submit" /> </Form>

Cuando enviemos un formulario así: se detonará la navegación, porque este <Form> hará una petición GET con los inputs como searchParams: /blog?search=react. 😱

Este pattern es muy útil dentro de React Router para detonar la ejecución del loader una segunda vez, pero con nuevos searchParams. De hecho, así es como funciona el buscador de fixtergeek.com 🤠 

👀 Recuerda que un formulario usa los mismos inputs para cualquier petición, ya sea GET o POST. Cuando es una petición GET los envía en forma de searchParams añadiéndolos en la propia URL. Pero, cuando es una petición POST, los entregará dentro de un FormData. 🪢

No dejes de leer el libro que te digo. 😒

redirect() desde el servidor

Como te he dicho antes, yo prefiero, siempre que puedo, la manera declarativa. Osea que uso bastante el componente <Form> incluso para navegar. Así que todo el tiempo estoy redireccionando desde el servidor. Sobre todo, dentro de las funciones action. Para ello, tenemos a la mano el helper redirect. ↪️

import { redirect } from "react-router"; export async function action({ request }) { const formData = await request.formData(); const newProduct = await createProduct(formData); return redirect(`/products/${newProduct.slug}`); }

Este pattern, es uno de los **más comunes en la web; pues redirect es solo un wrapper, una utilidad, que, por debajo, emplea un Response nativo de la fetch API. 😬

👀 Podríamos sustituir un redirect con un: new Response.redirect(url). 🤯

Este helper vendrá a ser útil también en las funciones loader del módulo de ruta. Para proteger una ruta privada, por ejemplo. 🙌🏼

import { redirect } from "react-router"; export async function loader({ request }) { const user = await getUserOrNull(request); if (!user) { return redirect("/login"); } return { user }; }

Ya para terminar: useNavigate

Este hook es para el cliente; lo podremos usar en cualquiera de nuestros componentes. 🧱

import { useNavigate } from "react-router"; export default function Route() { const navigate = useNavigate(); const handleSubmit = (event) => { // ... masajeamos y mandamos con fetcher.submit // para luego navegar, por ejemplo... navigate('/dashboard/products') // vamos a donde sea. } return (<form onSubmit={handleSubmit}> {/** */} </form>) }

No te dejes influenciar demasiado por mis ejemplos, navigate puede usarse imperativamente (programáticamente) dentro de cualquier función; puedes usarla en un <button> o dentro de un useEffect; tú decides, tú eres el(la) desarrollador(a) front end. 🤷🏻‍♀️

👀 Aunque puedes usar este hook cuando necesites navegar sin una interacción del usuario, la documentación oficial nos recomienda evitarlo todo lo posible y preferir el uso de los otros métodos antes vistos. ⛔️

Bueno bueno, ¡mírate nomás! Ya eres todo un(a) experto(a) en las herramientas de este Framework. Ya navegas de un lado para el otro sin pedir permiso. Bien hecho mi niño. 👦🏻👧🏻

Enlaces relacionados

Hypermedia systems

Response.redirect nativo