Contenido del curso
Webpack
Parcel
ESBuild
Rollup
Vite
Conclusiones
useState y useCallback en un contador React
Resumen
Construir un contador en React con TypeScript y empaquetarlo con esbuild es uno de los ejercicios más claros para entender cómo funcionan los hooks y los bundlers modernos. Aquí trabajamos la lógica del componente con useState y useCallback, y luego preparamos el build con esbuild para servirlo en el navegador.
¿Cómo se conecta useState con la acción de incrementar?
La idea es sencilla: necesitas un valor que cambie en el tiempo y una función que lo actualice. Eso es justo lo que entrega useState.
Dentro del componente, antes del return, declaras una constante con dos posiciones: la primera guarda el estado, la segunda es la función que lo modifica. Por convención, la función lleva el prefijo set seguido del nombre de la variable.
tsx const [count, setCount] = useState(0);
El argumento que recibe useState es el valor inicial. Puede ser un string, un número o incluso una función, aunque para casos avanzados conviene usar otras herramientas que se cubren en el curso de React Hooks. En este caso, inicializas en cero y el warning sobre count desaparece, porque ya existe un valor en el primer render.
¿Qué hace useState en React? Devuelve un arreglo con dos elementos: el estado actual y una función para actualizarlo. Cada vez que llamas a la función set, React vuelve a renderizar el componente con el nuevo valor.
¿Por qué usar useCallback para la función increment?
useCallback memoriza la función para que no se vuelva a crear en cada render, salvo que cambien sus dependencias. Es útil cuando pasas funciones como props o cuando dependes de un valor que cambia.
La estructura tiene dos argumentos: una función anónima y un arreglo de dependencias. Aquí escuchas los cambios de count para que la lógica se mantenga sincronizada.
tsx const increment = useCallback(() => { setCount(count + 1); }, [count]);
Luego, en el botón, conectas la acción con el evento onClick, que es parte del sistema de manejo de eventos que provee React.
tsx <button onClick={increment}>Increment</button>
Finalmente, exportas el componente con export default App para que pueda consumirse desde index.
¿Cómo preparar el bundle con esbuild?
Antes del build necesitas un index.html. Crea una carpeta public en la raíz del proyecto y dentro un archivo index.html con el shortcut de Emmet en Visual Studio Code. En el body agrega un div con el ID App, que es el contenedor donde React DOM montará la aplicación.
Esbuild puede usarse de dos formas: directamente desde un script en package.json o con un archivo de configuración aparte. Empezamos por el script.
¿Qué script de build configurar en package.json?
Reemplaza la línea de test y crea uno llamado build con las instrucciones que esbuild necesita en una sola línea:
- bundle: empaqueta todas las dependencias.
- minify: reduce el tamaño del archivo final.
- sourcemap: genera el mapa para depurar desde Chrome.
- outfile: define la ruta de salida, en este caso public/bundle.js.
"build": "esbuild source/index.tsx --bundle --minify --sourcemap --outfile=public/bundle.js"
Al ejecutar npm run build, el compilado tarda alrededor de 33 milisegundos la primera vez y baja a 18 milisegundos en la segunda corrida, gracias al sistema de caché interno que reconoce librerías ya procesadas.
Después, en el index.html agregas el script con defer apuntando a ./bundle.js para que cargue el bundle generado.
html
<script defer src="./bundle.js"></script>¿Cómo crear un entorno de desarrollo local con esbuild?
Para probar la app sin levantar manualmente cada cambio, instalas la dependencia que habilita el entorno local:
bash npm install esbuild @esbuild/serve --save-dev
Luego creas un archivo esbuild.dev.js en la raíz del proyecto. Es importante validar que esté en la raíz para evitar problemas de identificación.
js require('esbuild').build({ entryPoints: ['source/index.tsx'], bundle: true, minify: true, sourcemap: true, outfile: 'dist/bundle.js' }).catch(() => process.exit(1));
El catch con process.exit(1) mata el proceso si algo falla, evitando que se quede esperando indefinidamente. Si pasaras 0, el programa continuaría sin marcar error.
¿Para qué sirve el sourcemap en esbuild? Permite que las herramientas de depuración de Chrome muestren el código original en lugar del bundle minificado, lo que facilita encontrar errores en desarrollo.
¿Qué scripts agregar para desarrollo y apertura del proyecto?
En package.json sumas tres scripts útiles:
- build:dev: ejecuta node esbuild.dev.js y genera el bundle en dist.
- start: corre node esbuild.dev.js con el flag watch para escuchar cambios.
- open: abre public/index.html directamente en el navegador.
Al correr npm run open, el contador se renderiza desde el index.html leyendo el archivo JavaScript ya compilado, sin necesidad de un servidor local. Es la prueba de que tanto el componente como el primer build con esbuild funcionan correctamente.
Con npm run build:dev se construye dentro de la carpeta dist, replicando lo que hicimos con la línea del script en package.json pero ahora desde el archivo de configuración.
¿Cómo te imaginas extender este contador para guardar el valor entre recargas? Cuéntalo en los comentarios y compara tu enfoque con el de otros estudiantes.