Avances en el desarrollo de Unix UI

Ángel Ortega
4 min readSep 18, 2024

En las últimas semanas, he estado inmerso en el desarrollo de mi propia librería UI llamada Unix UI. Este proyecto ha sido una gran oportunidad para profundizar en cómo React maneja la creación de componentes, y hoy quiero compartir algunos de los retos que he enfrentado, en particular al trabajar con React.createElement.

¿Qué es Unix UI?

Para quienes no estén familiarizados, Unix UI es una librería de componentes que busca ofrecer una solución minimalista y eficiente para construir interfaces de usuario. El objetivo principal es proporcionar una colección de componentes reutilizables y altamente personalizables que simplifiquen el desarrollo de interfaces web.

Desafíos y Soluciones en el Desarrollo de Componentes React Dinámicos.

En el proceso de desarrollo de una aplicación React, nos hemos enfrentado a varios desafíos técnicos relacionados con la gestión de estados, contextos, animaciones y tipado en TypeScript. A continuación, se describen los problemas que encontramos y cómo los hemos resuelto, lo que ha contribuido a avanzar en el proyecto y mejorar nuestra comprensión de React y TypeScript.

Manejo del Contexto y setOutlet no es una Función.

Problema:

Al intentar actualizar el estado de un componente utilizando setOutlet, nos encontramos con el error:

setOutlet is not a function

Análisis:

Este error indicaba que setOutlet era undefined o no estaba accesible en el alcance donde se estaba utilizando. Al revisar el código, notamos que setOutlet debía provenir de un contexto (BlockContext), pero el componente que intentaba usarlo no estaba correctamente envuelto por el proveedor del contexto.

Solución:

  • Aseguramos que el componente consumidor (ChildComponent) estaba dentro del proveedor del contexto (BlockContext.Provider).
  • Verificamos que setOutlet estaba siendo proporcionado correctamente en el valor del contexto.
  • Utilizamos el hook useBlockContext para acceder al contexto en los componentes hijos.

Resultado:

Al corregir la estructura de los componentes y garantizar que el contexto estaba siendo utilizado correctamente, el error se resolvió, permitiendo que setOutlet se utilizara para actualizar el estado del componente.

Clonación de Elementos con React.cloneElement y Pasaje de Props.

Problema:

Al intentar clonar un elemento utilizando React.cloneElement y añadirle múltiples props adicionales (handleClick, setOutlet, newElement), solo una de las props era reconocida, y se generaba un error de TypeScript:

No overload matches this call.

Análisis:

Este error se debía a que el componente hijo que estábamos clonando no tenía definidas las props adicionales en su interfaz de props. TypeScript no podía confirmar que las props eran válidas para ese elemento, lo que generaba el error.

Solución:

  • Actualizamos la interfaz de props del componente hijo para incluir las nuevas props que deseábamos pasar.
  • Especificamos el tipo del elemento hijo al clonarlo, utilizando genéricos en React.cloneElement<ChildProps>(…).
  • Nos aseguramos de que child era un ReactElement y no un ReactNode, permitiendo a TypeScript inferir correctamente los tipos.

Resultado:

Con estas modificaciones, TypeScript reconoció las props adicionales, y pudimos clonar los elementos y pasarles múltiples props sin problemas.

Implementación de Animaciones entre Elementos con CSS y Transiciones.

Problema:

Queríamos añadir una animación entre la generación de un elemento y otro utilizando solo CSS, sin depender de librerías externas como react-transition-group. Al montar y desmontar componentes en React, los elementos aparecen o desaparecen instantáneamente del DOM, lo que complica la aplicación de animaciones con CSS puro.

Solución:

  • Creamos un componente personalizado CSSTransition que controla el montaje y desmontaje de elementos y aplica clases CSS en momentos específicos para desencadenar animaciones.
  • Utilizamos useState y useEffect para manejar el estado interno del componente y aplicar las clases correspondientes durante las transiciones.
  • Definimos las animaciones en CSS utilizando @keyframes y transiciones, asegurando que los elementos tengan una animación suave al entrar y salir del DOM.

Resultado:

Al integrar CSSTransition en nuestros componentes, logramos animar las transiciones entre diferentes elementos sin depender de librerías externas, manteniendo un control total sobre las animaciones y mejorando la experiencia del usuario.

Gestión Recursiva de Estados y Actualización Dinámica de Contenido

Problema:

Necesitábamos que al modificar el estado (setId), se actualizara el componente anterior, permitiendo una especie de recursividad en la actualización del contenido. Esto era especialmente relevante al mostrar una lista de elementos y permitir al usuario ver detalles específicos al seleccionar uno.

Solución:

  • Centralizamos el estado Id en un componente padre (ChildComponent) y lo pasamos como prop a los componentes hijos que lo necesitaban.
  • Ajustamos el componente Block para pasar correctamente las props a newElement y los hijos clonados.
  • Eliminamos efectos innecesarios que causaban ciclos infinitos y reorganizamos la lógica para asegurar que las actualizaciones de estado provocaran los re-renderizados deseados.

Resultado:

Con estas modificaciones, logramos que al actualizar setId, el componente se re-renderizara recursivamente, mostrando el contenido adecuado en función del estado actual. Esto permitió crear una navegación fluida entre la lista de elementos y los detalles de cada uno.

Conclusiones

A través de la identificación y solución de estos problemas, hemos avanzado significativamente en el desarrollo de unix ui. No solo hemos resuelto los errores inmediatos, sino que también hemos:

  • Mejorado nuestra comprensión de cómo funciona el contexto en React y cómo compartir estados entre componentes.
  • Aprendido a manejar el tipado en TypeScript al trabajar con componentes genéricos y funciones como React.cloneElement.
  • Ganado experiencia en la creación de componentes personalizados para manejar animaciones sin depender de librerías externas.
  • Fortalecido nuestras habilidades en la gestión de estados y la actualización dinámica de contenidos en aplicaciones React.

Aunque aún queda trabajo por hacer, estos avances en Unix UI me han permitido optimizar la forma en la que construyo componentes y evitar errores comunes. Continuaré afinando la librería y explorando nuevas formas de mejorar la construcción dinámica de interfaces.

--

--

Ángel Ortega
Ángel Ortega

No responses yet