Índice de contenidos
- Introducción
- Server Side Rendering
- Problemática con las peticiones
- Introducción a los React Server Components
- Conclusión
Introducción
Los React Server Components han llegado!?. El nuevo paradigma el cual nos permite cargar componentes de React únicamente en el servidor ya están aquí. En este tutorial vamos vamos a ver de forma resumida sus características y los increíbles beneficios que estos nos aportan.
Server Side Rendering ?️
Para poner en contexto los RSCs (React Server Components) considero importante conocer primero en que consiste el Server Side Rendering (SSR). Si ya estás familiarizado con SSR puedes avanzar a la siguiente parte donde hablo exclusivamente de los RSCs.
Hasta no hace mucho lo más normal ha sido usar Client Side Rendering (CSR), mediante el CSR el usuario recibe un archivo HTML el cuál carga un script con el bundle.js
, este script es el que contiene todo lo necesario para montar la aplicación.
Una vez el JavaScript termina de descargarse, React empieza a construir la aplicación bajo el #root
de React. El problema está en que mientras todo esto ocurre, el usuario esta viendo una pantalla en blanco. Además cuanto mas crece el bundle, mayor es el tiempo de espera del usuario.
Aquí es donde entra en juego el SSR. En el SSR el servidor renderiza la aplicación y genera el HTML que será enviado al cliente, de esta forma no recibe un HTML vacío como con el CSR. Este archivo HTML incluirá igualmente el script ya que seguiremos necesitando que React se ejecute en la parte del cliente cuando ocurra cualquier interacción por parte del usuario.
Mediante el SSR, React se configura de manera diferente ya que en lugar de crear los nodos desde cero, utiliza el HTML ya renderizado en el servidor y crea en su virtual dom que viene a ser un copia del dom y añade los controladores de eventos etc. Este proceso se le denomina Hydration.
Digamos que en el proceso de hidratación es como si a un árbol seco como puede ser ese primer HTML que recibimos del servidor lo regásemos o hidratásemos con la posibilidad de interacción, control de eventos etc.
Y resumidamente en esto consiste el SSR.
Problemática con las peticiones ?
Hasta ahora en React mediante el CSR cuando queríamos hacer una petición se nos juntaban dos problemáticas, la primera que ya hemos comentado en la que el usuario tenía que esperar mediante una pantalla en blanco debido al renderizado en la parte del cliente y en adición una nueva espera en la petición de datos, donde mostramos el layout general. Generalmente la parte de la aplicación en la que mostraríamos esos datos aparece en un estado de loading. Una vez el contenido ya este disponible si que se mostraría la aplicación con los datos.
Mediante el SSR se ha solventado el primero de los problemas, por lo que esa primera espera en la que la pantalla está en blanco va a ocurrir mucho más rápido y permite al usuario interactuar con elementos que no hacen esa petición de datos. Esto es un avance pero sinceramente, el usuario no esta visitando tu web para ver una pantalla de loading.
Y… ¿Por qué no hacemos esa petición de datos durante la petición inicial del servidor?
Pues algunos frameworks de React como Next.js y Gatsby han creado una forma de hacer esto posible mediante código que se ejecuta exclusivamente en el servidor. Hay que decir que esto es un gran avance pero sigue teniendo algunos problemas:
- Esta estrategia únicamente ocurre a nivel de ruta, para componentes de nivel superior. No sirven para cualquier componente.
- No existe un estándar.
- Los componentes de React, van a hidratarse en la parte del cliente siempre, aunque no sea necesario.
La solución final a estos problemas son los llamados React Server Components.
Introducción a los React Server Components ⚛️
Con los nuevos React Server Components (RSCs) podemos crear componentes que se ejecuten exclusivamente en el servidor.
Una parte muy clave para entender los React Server Components es que estos componentes renderizados en el servidor, no se vuelven a renderizar. Es decir, una vez generada la interfaz, esta será inmutable.
Efectivamente, esto quiere decir que una gran parte del API de React no es compatible, el uso de useState
o useEffect
no esta soportado por los RSCs.
Realmente los React Server Components son sorprendentemente sencillos, lo realmente complejo es integrarlos con los componentes de React que conocemos hasta ahora. A estos les podemos llamar «Client Components» pese a que son renderizados tanto en el servidor como en el cliente.
Aunque es cierto que el uso de RSCs no te obliga a utilizar SSR, si que es cierto que es una práctica recomendable.
Quiero empezar a usar React Server Components ⭐
Por el momento hasta la fecha de publicación de este tutorial la única forma de utilizar RSCs es mediante Next.js a partir de la versión 13.4 en adelante, mediante su nuevo App Router
Por defecto con este nuevo enfoque, todos los componentes son Server Components por defecto, es decir lo que vamos a tener que indicar es que componentes son «Client Components»
Para hacerlo es tan fácil como usar la nueva directiva 'use client’
, de esta forma le estamos diciendo a React que incluya este componente en el bundle de JavaScript.
'use client';
import React from 'react';
export default function Counter() {
const [count, setCount] = React.useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>
Incrementar
</button>
<span>Valor: {count}</span>
</>
);
}
Como he dicho antes, los componentes son Server Components por defecto por lo que no debemos usar la directiva 'use server’
para indicar que es un RSCs. De hecho esa directiva corresponde a las Server Actions, que no tienen nada que ver con este tema.
Trabajando con RSCs y RCCs ?️
Es probable que te estes preguntando que pasa cuando cuando un componente padre contiene un estado por ejemplo, este componente va a tener que ser renderizado en el cliente como ya hemos hablado antes. ¿Qué ocurre con sus hijos que sí son RSCs?
Pues efectivamente en el momento que el componente padre tuviese que re-renderizarse, todos sus componentes hijos lo harían también.
Para evitar esta situación contradictoria e imposible, el equipo de React añadió una regla que consiste en que un «Client Component» solo puede importar otros «Client Components».
Esto quiere decir que cuando utilizamos el 'use client’
en un componente que tiene componentes hijos estos se convierten en «Client Components», a esto se le llama “Client Boundary”. Esto significa que los componentes hijos no tienen la necesidad de utilizar el 'use client’
en ellos.
Entonces te habrás preguntado, si tengo tengo la necesidad de tener un «Client Component» en una parte muy alta del árbol de componentes debido a que tengo un estado por ejemplo, ¿todos los componentes van a ser «Client Components»?
La respuesta es sí, pero en la mayoría de casos esto puede ser resuelto mediante una reestructuración de nuestra aplicación. Veámoslo con un ejemplo:
'use client';
import { Languages } from '@/languages.js';
import Header from './Header';
import MainContent from './MainContent';
function Homepage() {
const [currentLanguage, setCurrentLanguage] = React.useState(Languages.ES);
return (
<Container language={currentLanguage}>
<Header />
<MainContent />
</Container>
);
}
En este caso vemos como la página principal contiene un estado para gestionar el idioma en la aplicación. Es por esto que Homepage
tiene que ser un «Client Component» e implícitamente los componentes Header
y MainContent
también.
Ahora vamos a ver como podemos refactorizar este código para que esto no ocurra. Para esto, nos llevamos el estado a un fichero a parte.
'use client';
import { Languages } from '@/languages.js';
function LanguageProvider({ children }) {
const [currentLanguage, setCurrentLanguage] = React.useState(Languages.ES);
return (
<Container language={currentLanguage}>
{children}
</Container>
);
}
Y modificamos la Homepage
para que utilice el LanguageProvider
.
import Header from './Header';
import MainContent from './MainContent';
import ColorProvider from './LanguageProvider';
function Homepage() {
return (
<LanguageProvider>
<Header />
<MainContent />
</LanguageProvider>
);
}
Como puedes apreciar, hemos podido quitar el ‘use client’
de la Homepage
ya que no utiliza ninguna característica de React que necesite el cliente. Esto significa que Header
y MainContent
ya no se convertirán en “Client Components».
Con lo que te tienes que quedar de todo esto es que realmente la relación padre/hijo no importa, ya que, aunque LanguageProvider
sea el padre tanto de Header
como de MainContent
es el componente Homepage
el que se encarga de importar, renderizar y por lo tanto, decidir que props reciben estos componentes y como Homepage
ahora es un Server Component, no tenemos ningún problema.
Conclusión ?
En resumen, la mayor ventaja que nos aportan los React Server Components es el rendimiento ya que estos no se incluyen en el bundle de la aplicación, lo que reduce la cantidad de JavaScript que tenemos que descargar y la cantidad de componentes que hidratar. Para mi es una característica muy interesante, aunque ésta solo forma una pequeña parte de todas las nuevas increíbles características que esta desarrollando React ?.
Muchas gracias por tu atención ??.