Mi ejemplo favorito es una tabla de API que muestra documentación para un componente de UI o software de cualquier tipo. Para que todo sea legible y hermoso, a veces estamos renderizando markdown con bloques de código en su interior, pero las bibliotecas de markdown son pesadas y a menudo terminan en tu paquete del cliente. Es aún peor si quieres resaltar la sintaxis para los bloques de código.
Lo que quiero poder hacer es renderizar una celda de markdown sin afectar el código del cliente. Sé que hay otras formas de lograr esto, pero la implementación más sencilla para mí sería algo como esto, pasando una celda especializada que haga todo el trabajo sin afectar negativamente el paquete del cliente.
Ahora, profundicemos en cómo podemos lograr esto utilizando un patrón que he llamado componente polimórfico, un componente que puede renderizar cualquiera de sus nodos tanto en el cliente como en el servidor. Para lograr esto, simplemente debemos seguir algunas reglas básicas. Primero, los componentes no deben renderizar sus propios hijos. Y segundo, su lógica del cliente debe estar separada.
Con esas dos reglas simples, podremos renderizar componentes personalizados en todo el árbol de componentes sin romper la funcionalidad del cliente y aún así poder convertirnos en un componente completamente del cliente para aplicaciones que no admiten o no requieren componentes del servidor. Si aplicamos esas reglas correctamente, el árbol de renderizado debería verse algo así. Cada nodo en el árbol es agnóstico, lo que significa que se puede renderizar tanto como un componente del cliente como del servidor. Además, las partes del cliente de un componente se extraen en una estructura de cliente donde no afectan el renderizado del componente original.
Ahora repasemos la primera regla de no ser responsable de tus propios hijos en el contexto de los componentes de UI, por supuesto. Si anteriormente nuestro componente raíz de la tabla de datos estaba renderizando directamente el rol, ahora estamos introduciendo un componente intermedio. Aún no he encontrado un buen nombre para ellos, pero por ahora los llamo componentes de vista. La idea de un componente de vista es ensamblar la ranura real que se puede personalizar, en nuestro caso el rol, y preparar a sus hijos para que si el rol necesita ser un componente del cliente o del servidor, sus hijos, las celdas, no se vean afectados por esta decisión, lo que les permite ser cualquier cosa según los requisitos de la aplicación.
Volviendo a nuestro caso de uso con la celda de markdown, el patrón de renderizado nos permitiría renderizar un componente del servidor en una hoja sin importar cualquier otra personalización que hayamos realizado en el árbol. Ahora pasemos a nuestra segunda regla. Eventualmente, tú o tu gerente de producto querrán agregar una función simple de selección de roles y no les importará mucho la implicación de rendimiento si llevamos todo el componente al cliente.
Cuando estaba jugando por primera vez con los componentes del servidor, pensé que simplemente podía agregar cualquier cosa de React a un componente y funcionaría en el servidor en lugar del cliente. Pero si intentas agregar estado a un componente, que podría renderizarse en el servidor, como nuestras partes agnósticas de la tabla de datos, rápidamente te encontrarás con un error. Lo mismo ocurre al adjuntar eventos DOM, porque ¿cómo más sabrías cómo cambiar el estado? Entonces, lo que estamos viendo en la pantalla ahora no funciona.
Para que funcione, debemos extraer toda la lógica del cliente en un componente separado. Una vez más, el mejor nombre que se me ocurrió es agregar 'cliente' al final del nombre del componente. Esto nos permite evitar el renderizado del componente sin afectar directamente el árbol y solo proporcionar el contexto del cliente. Esto nos permite consumir este contexto desde la parte del cliente de nuestros otros componentes. Nuevamente, solo agregando lógica específica del cliente.
En nuestro caso de uso, eso sería la parte del cliente del rol, que solo debe agregar un evento de clic y agregar un nombre de clase si el estado del cliente indica que el rol está seleccionado. Ampliando la vista para ver la imagen completa, nuestros componentes móviles se ven así, renderizando de izquierda a derecha y su lógica del cliente se extrae en un componente separado con la directiva 'cliente'.
Comments