Componentes de Servidor y Cliente

Para entender cómo funcionan los Componentes de Servidor y Cliente, es útil familiarizarse con dos conceptos fundamentales de la web:

  • Los entornos donde se puede ejecutar el código de tu aplicación: el servidor y el cliente.
  • El límite de red que separa el código del servidor y del cliente.

Entornos de Servidor y Cliente

En el contexto de aplicaciones web:

Diagrama que muestra un navegador a la izquierda y un servidor a la derecha, separados por un límite de red.
  • El cliente se refiere al navegador en el dispositivo del usuario que envía una solicitud a un servidor para obtener el código de tu aplicación. Luego convierte la respuesta recibida del servidor en una interfaz con la que el usuario puede interactuar.
  • El servidor se refiere a la computadora en un centro de datos que almacena tu código de aplicación, recibe solicitudes de un cliente, realiza cálculos y envía una respuesta adecuada.

Cada entorno tiene su propio conjunto de capacidades y limitaciones. Por ejemplo, al mover el renderizado y la obtención de datos al servidor, puedes reducir la cantidad de código enviado al cliente, lo que puede mejorar el rendimiento de tu aplicación. Pero, como aprendiste anteriormente, para hacer que tu interfaz sea interactiva, necesitas actualizar el DOM en el cliente.

Por lo tanto, el código que escribes para el servidor y el cliente no siempre es el mismo. Ciertas operaciones (como la obtención de datos o la gestión del estado del usuario) son más adecuadas para un entorno que para el otro.

Límite de Red

El Límite de Red es una línea conceptual que separa los diferentes entornos.

En React, tú decides dónde colocar el límite de red en tu árbol de componentes. Por ejemplo, puedes obtener datos y renderizar las publicaciones de un usuario en el servidor (usando Componentes de Servidor), y luego renderizar el botón interactivo LikeButton para cada publicación en el cliente (usando Componentes de Cliente).

De manera similar, puedes crear un componente Nav que se renderice en el servidor y se comparta entre páginas, pero si deseas mostrar un estado activo para los enlaces, puedes renderizar la lista de Links en el cliente.

Un árbol de componentes que muestra un diseño con 3 componentes como hijos: Nav, Page y Footer. El componente Page tiene 2 hijos: Posts y LikeButton. El componente Posts se renderiza en el servidor, y el componente LikeButton se renderiza en el cliente.

Detrás de escena, los componentes se dividen en dos grafos de módulos. El grafo de módulos del servidor (o árbol) contiene todos los Componentes de Servidor que se renderizan en el servidor, y el grafo de módulos del cliente (o árbol) contiene todos los Componentes de Cliente.

Después de que los Componentes de Servidor se renderizan, se envía al cliente un formato de datos especial llamado React Server Component Payload (RSC). El payload RSC contiene:

  1. El resultado renderizado de los Componentes de Servidor.
  2. Marcadores de posición (o "huecos") para indicar dónde deben renderizarse los Componentes de Cliente y referencias a sus archivos JavaScript.

React usa esta información para consolidar los Componentes de Servidor y Cliente y actualizar el DOM en el cliente.

Veamos cómo funciona esto.

Usando Componentes de Cliente

Como aprendiste en el capítulo anterior, Next.js usa Componentes de Servidor por defecto - esto mejora el rendimiento de tu aplicación y significa que no tienes que tomar pasos adicionales para adoptarlos.

Volviendo al error en tu navegador, Next.js te está advirtiendo que estás intentando usar useState dentro de un Componente de Servidor. Puedes solucionar esto moviendo el botón interactivo "Like" a un Componente de Cliente.

Crea un nuevo archivo llamado like-button.js dentro de la carpeta app que exporte un componente LikeButton:

/app/like-button.js
export default function LikeButton() {}

Mueve el elemento <button> y la función handleClick() de page.js a tu nuevo componente LikeButton:

/app/like-button.js
export default function LikeButton() {
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

Luego, mueve el estado likes y el import:

/app/like-button.js
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0);
 
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

Ahora, para hacer que LikeButton sea un Componente de Cliente, agrega la directiva 'use client' de React al inicio del archivo. Esto le indica a React que renderice el componente en el cliente.

/app/like-button.js
'use client';
 
import { useState } from 'react';
 
export default function LikeButton() {
  const [likes, setLikes] = useState(0);
 
  function handleClick() {
    setLikes(likes + 1);
  }
 
  return <button onClick={handleClick}>Like ({likes})</button>;
}

De vuelta en tu archivo page.js, importa el componente LikeButton en tu página:

/app/page.js
import LikeButton from './like-button';
 
function Header({ title }) {
  return <h1>{title ? title : 'Default title'}</h1>;
}
 
export default function HomePage() {
  const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];
 
  return (
    <div>
      <Header title="Develop. Preview. Ship." />
      <ul>
        {names.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
      <LikeButton />
    </div>
  );
}

Guarda ambos archivos y revisa tu aplicación en el navegador. Ahora que no hay errores, cuando hagas cambios y guardes, deberías notar que el navegador se actualiza automáticamente para reflejar el cambio.

Esta característica se llama Fast Refresh. Te brinda retroalimentación instantánea sobre cualquier edición que hagas y viene preconfigurada con Next.js.

Resumen

Para recapitular, aprendiste sobre los entornos de servidor y cliente y cuándo usar cada uno. También aprendiste que Next.js usa Componentes de Servidor de React por defecto para mejorar el rendimiento, y cómo puedes optar por usar Componentes de Cliente para hacer pequeñas partes de tu interfaz interactivas.

Lectura Adicional

Hay mucho más por aprender sobre Componentes de Servidor y Cliente. Aquí hay algunos recursos adicionales:

On this page