Contenido
Migrar desde React
Carats está deliberadamente cerca de React, así que la mayor parte del código de los componentes se porta directamente. Las diferencias de abajo son las que realmente rompen un port.
| Concepto | React | Carats |
|---|---|---|
| Entorno de ejecución | React, React DOM y un DOM virtual | Solo JJSX; los componentes son funciones que devuelven HTML |
| Estado | useState vuelve a renderizar el componente | use guarda un valor; el DOM se actualiza a mano |
| Efectos | useEffect con un array de dependencias | afterMount (tras la carga) o beforeMount (inmediato), sin dependencias |
| Manejadores de eventos | <button onClick={fn}> | addEventListener dentro de una llamada de hook |
| Enrutamiento | Un enrutador de sistema de archivos con diseños y rutas anidadas | Un mapa de defineFacets, compuesto importando un diseño |
| Datos del servidor | getServerSideProps en la página | Un culet por ruta más un envoltorio Burnish |
| Cabecera del documento | next/head o la exportación de metadatos del framework | this.head dentro de un componente de función |
| Metadatos del componente | Component.displayName, memo y context | defaultProps en el componente; sin context ni memo |
| Estilos | CSS-in-JS o clases utilitarias | SASS con alcance que importa tokens de diseño compartidos |
| Tipos | Interfaces importadas por archivo | Interfaces DTO globales desde src/dto |
Manejadores de eventos
El modelo de eventos es el cambio que más a menudo rompe una migración, así que conviene ser preciso con él.
// React
<button onClick={() => setOpen(!open)}>Toggle</button>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
// Carats
import { use, afterMount } from '@carats/hooks';
export default function Toggle() {
const open = use(false);
afterMount(() => {
const button = document.getElementById('toggle');
const stop = open.subscribe((value) => {
button?.setAttribute('aria-expanded', String(value));
});
const onClick = () => open.set(!open.get());
button?.addEventListener('click', onClick);
return () => {
stop();
button?.removeEventListener('click', onClick);
};
});
return <button id="toggle" aria-expanded="false">Toggle</button>;
}
Estado
useState pasa a ser use, y cada renderizado que React se habría encargado se convierte en una escritura explícita del DOM. El estado que era local a un componente no cambia en esencia: llama a use en el nivel superior del componente, léelo con get y escríbelo con set.
Enrutamiento
El enrutador del sistema de archivos se colapsa en un único objeto. Cada ruta se convierte en una entrada de defineFacets, y los diseños anidados se convierten en un import explícito. Como el objeto de facetas es compartido, una ruta que falte en él falta tanto en el cliente como en el servidor, lo que elimina toda una clase de errores.
Datos del servidor
getServerSideProps pasa a ser un culet, y la página pasa a estar bruñida. La firma de la función mantiene la misma forma: entra la petición, salen los datos.
// React / Next.js
export async function getServerSideProps({ params }) {
return { props: { symbol: params.symbol } };
}
// Carats
export default culet<TradeData>('/trade/:symbol', async (req) => {
return { symbol: req.params.symbol.toUpperCase() };
});
// Carats page
export default Burnish<TradeData>(function (data) {
return <h1>{data.symbol}</h1>;
});
Cabecera del documento
Una exportación de metadatos pasa a ser this.head, y el componente tiene que ser una declaración function para que exista this. Un componente que ya es una función de flecha puede seguir siéndolo, a costa de no aportar etiquetas head.
Estilos
CSS-in-JS no tiene equivalente. Cada componente importa un archivo SASS, ese archivo importa base.sass para los tokens de diseño, y los tokens viven en el nivel superior de esa única hoja de estilos global.
Lista de comprobación de la migración
- Borra react, react-dom y todas las dependencias que solo usen React.
- Sustituye los atributos de evento por addEventListener dentro de una llamada afterMount o beforeMount.
- Convierte cada ruta basada en archivos en una entrada del mapa de facetas, e importa un diseño compartido de forma explícita.
- Mueve el cuerpo de getServerSideProps a los culets y envuelve la página con Burnish.
- Mueve useState a use y añade la actualización manual del DOM que hacía el rerenderizado.
- Mueve la exportación head a this.head en un componente de función.
- Sustituye CSS-in-JS por archivos SASS que importa cada componente.