Enrutamiento, el componente Link

El componente <Link> extiende la etiqueta HTML <a> para ofrecer prefetching y navegación del lado del cliente entre rutas. Es la forma principal y recomendada para navegar entre rutas en Next.js.

Se puede importar desde el paquete next/link y requiere que se asigne la ruta destino al prop href.

import Link from 'next/link'

export default function Page() {
    return <Link href="/dashboard">Dashboard</Link>
}

Esta tabla es una lista de props disponibles para el componente <Link>

Prop Ejemplo Tipo Requerido
href href="/dashboard" String u Objeto Si
replace replace={false} Boolean
scroll scroll={false} Boolean
prefetch prefetch={false} Boolean o null

Los atributos de la etiqueta <a> como className o target="blank" pueden ser utilizados en el componente <Link> como props, y serán asignados a su etiqueta <a> interna.

replace

Por defecto es false. Cuando es true, next/link reemplazará el estado actual del historial en lugar de agregar una nueva URL en la pila de historial del navegador.

import Link from `next/link`;

export default function Page(){
    return (
        <Link href="/dashboard" replace>
            Dashboard
        </Link>
    )
}

prefetch

El prefetching ocurre cuando un componente <Link /> entra en el campo de visión del usuario (ya sea inicialmente o al desplazarse). Next.js realiza una precarga y carga en segundo plano de la ruta enlazada (indicada por el href) y sus datos para mejorar el rendimiento de las navegaciones del lado del cliente. El prefetching solo está habilitado en producción.

  • null (valor por default): El comportamiento del prefetch depende de si la ruta es estática o dinámica. Para rutas estáticas, se realizará el prefetch de la ruta completa (incluyendo todos sus datos). Para rutas dinámicas, se realizará el prefetch de la ruta parcial hasta el segmento más cercano con un límite de loading.js.

  • true: Se realiza el prefetch para ambas, rutas dinámicas y estáticas.

  • false: Nunca se realiza el prefetch.

Ejemplos

Enlazar a rutas dinámicas

Para rutas dinámicas, puede ser útil usar literales de plantilla para crear la ruta del enlace.

Por ejemplo, suponiendo que se quiera generar una lista de enlaces a la ruta dinámica app/blog/[slug]/page.tsx.

import Link `next/link`;

function Page({ post }) {
    return (
        <ul>
            {posts.map((post) => {
                return (
                    <li key={post.id}>
                        <Link href={`/blog/${post.slug}/`}>
                            {post.title}
                        </Link>
                    </li>
                )
            })}
        </ul>
    )
}

Si el componente hijo, es un componente que envuelve la etiqueta

Si el hijo del componente Link, es un componente personalizado que envuelve a la etiqueta <a>, se debe especificar el prop passHref. Esto es necesario si estas utilizando la librería styled-components. Si no se especifica, la etiqueta <a> no tendrá el atributo href, lo que afecta la accesibilidad del sitio web y puede afectar los resultados del SEO. Si estas usando Eslint, existe una regla next/link-passhref para asegurarse de utilizar passHref.

import Link from 'next/link'
import styled from 'styled-components'

const RedLink = styled.a`
    color: red;
`

function NavLink({ href, name }) {
    return (
        <Link href={href} passHref legacyBehavior>
            <RedLink>{name}</RedLink>
        </Link>
    )
}
  • Si estás utilizando la característica JSX pragma de emotion (@jsx jsx), debes usar passHref incluso si usas una etiqueta <a> directamente.

  • El componente debe soportar la propiedad onClick para activar la navegación correctamente.

Si el componente hijo, es un componente funcional

Si el hijo de Link es un componente funcional (hace uso de ref), además de usar passHref y legacyBehavior, debes envolver el componente en React.forwardRef:

import Link from 'next/link'

// `onClick`, `href`, and `ref` need to be passed to the DOM element
// for proper handling
const MyButton = React.forwardRef(({ onClick, href }, ref) => {
    return (
        <a href={href} onClick={onClick} ref={ref}>
            Click Aquí!
        </a>
    )
})

function Home() {
    return (
        <Link href="/about" passHref legacyBehavior>
            <MyButton />
        </Link>
    )
}

Objeto With URL

El componente Link también puede recibir un objeto URL y lo utilizara para crear el string de la URL solicitada.

import Link from `next/link`;

function Home()  {

    return (
        <div>
            {/* Genera una url /about?name=test */}
            <Link href={{ pathname: '/about', query: { name: 'test' } }}>
                About Us
            </Link>

            {/* Genera una url /blog/weather-today/ */}
            <Link href={{ pathname: '/blog/[slug]', query: { slug: 'weather-today' } }}>
                Blog
            </Link>
        </div>
    )

}

export default Home;

Para mas información sobre los parámetros disponibles en un objeto URl, consultar la Documentación Oficial de Nodejs

Replace en lugar de push

El comportamiento por default de Link es utilizar push, para agregar un nuevo URL a la pila del history. Puede utilizar replace para prevenir el agregar un nuevo valor a esta pila.

<Link href="/about" replace>
    Acerca de nosotros
</Link>

Deshabilitar el scroll hasta la parte inicial de la página

El comportamiento predeterminado de Link es desplazarse hasta la parte superior de la página. Cuando se define un hash, se desplazará al id específico, como una etiqueta <a> normal. Para evitar desplazarse hasta la parte superior/hash, se puede agregar scroll={false} a Link:

<Link href="#hashid" scroll={false}>
    Acerca De...
</Link>

Middleware

Es común usar Middleware para autenticación u otros propósitos que implican redirigir al usuario a una página diferente. Para que el componente <Link /> pueda prefetchar correctamente los enlaces con redirecciones a través de Middleware, necesitas decirle a Next.js tanto la URL a mostrar como la URL a prefetchar. Esto es necesario para evitar fetches innecesarios al middleware para conocer la ruta correcta a prefetchar.

Por ejemplo, si deseas servir una ruta /dashboard que tenga vistas autenticadas y de visitantes, puedes agregar algo similar a lo siguiente en tu Middleware para redirigir al usuario a la página correcta:

import Link from 'next/link'
import useIsAuthed from './hooks/useIsAuthed'

export default function Page() {
    const isAuthed = useIsAuthed()
    const path = isAuthed ? '/auth/dashboard' : '/public/dashboard/'

    return (
        <Link as="/dashboard/" href={path}>
            Dashboard
        </Link>
    )
}

Es posible utilizar el hook usePathname() para determinar si un link se encuentra activo. Por ejemplo, para agregar una clase al link activo, podemos verificar que el pathname actual coincida con el href del link:

import { usePathname } from 'next/navigation'
import Link from 'next/link'

export function Links() {
    const pathname = usePathname()

    return (
        <nav>
            <Link
                href="/"
                className={`link ${pathname === '/' ? 'active' : ''}`}
            >
                Home
            </Link>

            <Link
                href="/about"
                className={`link ${pathname === '/about' ? 'active' : ''}`}
            >
                About
            </Link>
        </nav>
    )
}

Conclusiones

En resumen, el componente <Link> de Next.js es una herramienta esencial para la navegación del lado del cliente en aplicaciones React, ofreciendo funcionalidades avanzadas como prefetching y navegación eficiente. Al utilizar props como href, replace, scroll y prefetch, se puede personalizar el comportamiento de los enlaces para mejorar la experiencia del usuario y el rendimiento de la aplicación. Además, es importante considerar el uso de passHref y legacyBehavior cuando se trabaja con componentes personalizados o funcionales para asegurar la accesibilidad y el SEO del sitio web.

Otros Artículos