Saltar al contenido

Navegación: el enlace A, useNavigate y saltos programáticos

Hay tres puertas para navegar en Solid, cada una para una intención distinta. El componente A es el enlace declarativo para el usuario, con estado activo automático y navegación del lado del cliente sin recarga. useNavigate da la navegación imperativa desde código, tras enviar un formulario o superar una guarda. Y el componente Navigate es la redirección declarativa en el render. Los tres comparten la transición del router, que mantiene la página vieja visible mientras la nueva carga.

El componente A: enlaces que conocen la ruta activa

A es el enlace de Solid, la alternativa al ancla cruda. La diferencia esencial es que A hace navegación del lado del cliente: intercepta el clic, cambia la ruta y actualiza solo lo que cambió, sin la recarga completa que provoca un ancla normal. Además aplica automáticamente una clase cuando su href coincide con la ruta actual —activeClass, que por defecto es active— y marca el enlace con aria-current="page" para accesibilidad.

TSX
import { A } from "@solidjs/router";export default function Menu() {  return (    <nav>      <A href="/" end>Inicio</A>      <A href="/blog" activeClass="activo" inactiveClass="apagado">Blog</A>    </nav>  );}

La prop end merece atención. Por defecto, A considera activo su enlace cuando el href es un prefijo de la ruta actual, de modo que /blog sigue activo en /blog/solid. Pero eso convertiría a / en activo en todas las rutas, porque / es prefijo de cualquier cosa; por eso al enlace de inicio se le pone end, que exige coincidencia exacta. Regla: usa end en enlaces raíz y en cualquier sitio donde no quieras el comportamiento de prefijo.

Prop de A Efecto
href destino de la navegación del lado del cliente
activeClass clase aplicada cuando coincide; por defecto active
inactiveClass clase aplicada cuando no coincide
end exige coincidencia exacta en vez de por prefijo
replace reemplaza la entrada de historial en vez de apilarla

Más allá de la clase activa, A acepta las opciones de navegación que esperarías: replace para no apilar historial, noScroll para no saltar al inicio de la página tras navegar, state para adjuntar datos a la entrada de historial, y los atributos nativos de un ancla como target. Bajo el capó sigue emitiendo un ancla real, accesible y con su href visible, de modo que abrir en pestaña nueva o copiar el enlace funcionan como el usuario espera; lo único que cambia es que el clic normal lo intercepta el router en vez del navegador.

useNavigate: navegar desde código

Cuando la navegación no nace de un clic sino de una consecuencia —un formulario que se guardó, una sesión que caducó—, necesitas navegar imperativamente. useNavigate devuelve una función navigate a la que le pasas un destino. Admite un número para moverte por el historial —navigate(-1) vuelve atrás— y un objeto de opciones con replace, state y scroll.

TSX
import { useNavigate } from "@solidjs/router";export default function Formulario() {  const navigate = useNavigate();  const enviar = async (datos: FormData) => {    await guardar(datos);    navigate("/gracias", { replace: true });  };  return <form action={enviar}>...</form>;}

Los destinos pueden ser absolutos —/gracias— o relativos a la ruta actual, y navigate acepta también un state que viaja con la navegación y luego lees con useLocation. Un patrón habitual: al enviar a login desde una guarda, guardas la ruta de origen en ese state para devolver al usuario exactamente adonde estaba una vez autenticado.

TSX
// Guardar la ruta de origen para volver tras el loginimport { useNavigate, useLocation } from "@solidjs/router";function useIrALogin() {  const navigate = useNavigate();  const location = useLocation();  return () => navigate("/login", { state: { volverA: location.pathname } });}

A veces la decisión de navegar es parte del render mismo: “si no hay sesión, redirige a login”. Para eso está el componente Navigate, que al renderizarse dispara la navegación. Es la forma declarativa de una guarda, sin efectos ni manejadores.

TSX
import { Navigate } from "@solidjs/router";import { Show } from "solid-js";export default function Privado(props) {  return (    <Show when={props.autenticado} fallback={<Navigate href="/login" />}>      {props.children}    </Show>  );}

En el servidor, dentro de acciones y consultas de SolidStart, existe además la función redirect, que devuelve una respuesta de redirección real; es la herramienta correcta para guardas que deben resolverse antes de enviar HTML. Pero para la redirección en el cliente durante el render, Navigate es la puerta directa.

Todo pasa por la misma transición

Las tres puertas comparten algo que conviene hacer explícito: ninguna recarga la página. A, navigate y Navigate disparan navegación del lado del cliente, y esa navegación va envuelta en la transición que el router aplica por defecto, la misma del nivel de transiciones. La página actual permanece visible mientras la ruta destino resuelve sus datos, y solo entonces se conmuta, sin parpadeo intermedio.

Elegir la puerta es, por tanto, una decisión de intención, no de mecanismo: por debajo obtienes el mismo comportamiento —transición, precarga al pasar el ratón sobre un A, conservación de la vista vieja— vengas de un enlace, de una llamada imperativa o de un redirect declarativo. Por eso puedes mezclarlas sin coste en una sola pantalla.

TSX
// Las tres puertas conviven en una pantallaimport { A, useNavigate, Navigate } from "@solidjs/router";import { Show } from "solid-js";function Pantalla(props) {  const navigate = useNavigate();  return (    <Show when={props.sesion} fallback={<Navigate href="/login" />}>      <A href="/inicio" end>Inicio</A>      <button onClick={() => navigate("/perfil")}>Ir al perfil</button>    </Show>  );}