Ir al contenido principal

El funcionamiento de React como un main event loop

 ¿Todas las aplicaciones de escritorio tienen un main event loop?

No, no todas las aplicaciones de escritorio tienen un bucle de eventos principal, aunque la gran mayoría de las que tienen una interfaz gráfica de usuario (GUI) sí lo tienen.

El concepto de un bucle de eventos principal (o main event loop) es un pilar fundamental de la programación de aplicaciones modernas. Es un mecanismo que espera, gestiona y responde a eventos, ya sean del usuario o del sistema. Sin él, la aplicación no podría responder a los clics del mouse, las pulsaciones del teclado o las actualizaciones de la pantalla.

¿Cómo funciona?

Imagina el bucle de eventos como el "corazón" de una aplicación gráfica. La aplicación se inicia, y el bucle principal comienza un ciclo infinito:

  1. Espera un evento: El bucle se pone en "modo de espera" hasta que ocurre algo (un clic, una tecla presionada, una ventana que necesita ser redibujada).

  2. Obtiene el evento: Cuando un evento sucede, el sistema operativo se lo notifica al bucle.

  3. Procesa el evento: El bucle ejecuta el código (la función o callback) asociado a ese evento.

  4. Vuelve a esperar: Una vez que el evento ha sido procesado, el bucle vuelve al paso 1.

Este ciclo interminable es lo que permite que una aplicación esté siempre "viva" y lista para la interacción.


Aplicaciones sin un bucle de eventos principal

Aunque es una característica casi universal en el desarrollo de GUI, no todas las aplicaciones lo necesitan.

  • Aplicaciones de línea de comandos (CLI): Estas aplicaciones son procedurales, no basadas en eventos. Su lógica es una secuencia de instrucciones que se ejecutan de arriba abajo. Una vez que la última instrucción se completa, el programa termina. No hay un bucle infinito que espere la interacción del usuario. Un ejemplo sería un script de PHP que procesa un archivo y luego sale.

  • Aplicaciones de un solo propósito: Un programa que realiza una tarea específica, como comprimir un archivo o generar un informe, no necesita un bucle de eventos. Su propósito es ejecutar una tarea y finalizar, no mantenerse activo para una posible interacción.


La abstracción de los frameworks

Es importante notar que, incluso en las aplicaciones con GUI, los desarrolladores de hoy en día rara vez escriben el bucle de eventos principal ellos mismos. Los modernos frameworks de GUI como Qt, GTK, Electron o WinForms abstraen y ocultan este bucle.

Como desarrollador, simplemente defines las acciones que deben ocurrir cuando sucede un evento (por ejemplo, onClick para un botón), y el framework se encarga de que su bucle principal llame a tu código cuando el evento se dispare.

En resumen, aunque el concepto de un bucle de eventos es vital para la programación de aplicaciones de escritorio interactivas, no todas las aplicaciones lo tienen.


Te pido que apliques los conceptos de main event loop que hablamos recién, para explicar cómo funciona react a un desarrollador de aplicaciones web.

Esa es una excelente forma de pensar en ello. La analogía del bucle de eventos principal de las aplicaciones de escritorio es perfecta para entender el corazón de React.

Un desarrollador web tradicional está acostumbrado al bucle de eventos del navegador: un click o un keypress dispara un callback de JavaScript que manipula directamente el DOM. El desarrollador es responsable de encontrar el elemento correcto y actualizar su contenido.

React, en cambio, abstrae ese proceso. Funciona con su propio bucle de eventos, que podemos llamar el "bucle de reconciliación", que corre por encima del bucle del navegador.


El bucle de reconciliación de React

Piensa en el bucle de React como un proceso que se activa en respuesta a un solo evento: un cambio de estado.

El bucle funciona en los siguientes pasos:

1. La "señal de entrada"

El bucle no se activa por un evento del navegador (como un clic), sino por un cambio en el estado de un componente, ya sea a través de useState, useReducer o cualquier otra función de actualización.

setContador(contador + 1);

Esta simple línea de código es la señal que le dice a React: "Oye, algo ha cambiado, es hora de que te pongas a trabajar".

2. La fase de renderizado y "diffing"

En esta fase, React hace un trabajo en memoria sin tocar el DOM real, que es la operación más costosa.

  • Renderizado: El bucle ejecuta la función de tu componente de nuevo y crea un nuevo Árbol del DOM Virtual con los valores de estado actualizados. Este árbol es una representación ligera del DOM real.

  • Diffing: React compara este nuevo Árbol del DOM Virtual con la versión anterior del árbol. Es increíblemente eficiente en encontrar las diferencias (el diff).

Este paso es como un ensayo general: todo el cálculo y la comparación se hacen en la memoria, sin que el usuario vea ningún cambio en la pantalla.

3. La fase de "commit"

Una vez que React sabe exactamente qué ha cambiado, pasa a la fase de commit.

  • Actualización del DOM real: El bucle ahora toma las diferencias que encontró en el paso anterior y actualiza solo los nodos del DOM real que lo necesitan. Si un elemento no ha cambiado, lo deja como está. Esto es lo que hace a React tan rápido.

4. Esperando el próximo evento

Una vez que el DOM real se ha actualizado y la pantalla ha cambiado, el bucle de React se detiene y entra en modo de espera, listo para la próxima vez que el estado de algún componente cambie.


En resumen, la principal diferencia con el modelo tradicional es que, en lugar de manipular el DOM directamente en respuesta a eventos del navegador, en React solo te preocupas por actualizar el estado. El bucle de reconciliación de React se encarga de todo lo demás: descubre qué cambió, lo compara eficientemente y actualiza el DOM de la manera más óptima posible. Esta abstracción te permite construir interfaces de usuario complejas de una forma mucho más declarativa e intuitiva.

Comentarios

Entradas populares de este blog

Crear proyecto de frontend con Vite, React, Tailwind, Typescript y JSX

 ¿Cómo se crea un proyecto exclusivo de frontend con Vite, React, Tailwind, Typescript y JSX? ¡Absolutamente! Entiendo que quieres la guía completa para pasar de cero a tener un proyecto de frontend moderno, vacío y listo para ser llenado con tu código. A continuación, te proporciono un archivo de guía detallada que incluye todos los comandos necesarios para inicializar el proyecto, configurar Tailwind CSS, y los pasos clave para empezar a "poblarlo". Voy a generar un documento Markdown con la guía paso a paso, incluyendo los comandos de terminal y las modificaciones esenciales a los archivos de configuración. Guía: Creación de un Proyecto Frontend Puro (Vite, React, TypeScript, Tailwind) Este documento detalla el proceso para inicializar un proyecto de frontend vacío y optimizado, utilizando Vite como empaquetador, React como librería, TypeScript para tipado y Tailwind CSS para estilizado. 1. Inicialización del Proyecto con Vite Vite es la herramienta más rápida para emp...

Tokens V2

Tokens: Programme to discover tokens, where there are not. Now available at  https://puszcza.gnu.org.ua/projects/tokens/ This is Version 2, for  version 1, go here . Synopsis: use TokensV2; sub printFile; my @FORMAT = ( ['<Message Date=".*?" Time=".*?" DateTime=".*?" SessionID=".*?"><From>(?:<User FriendlyName=".*?"/>)+</From><To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style=".*?")?>.*?</Text></Message>',   sub {     my $fh = $_[1];     my ($d, $t, $f, $s, $T) = $_[0] =~ m|<Message Date="(.*?)" Time="(.*?)" DateTime=".*?" SessionID=".*?">(<From>(?:<User FriendlyName=".*?"/>)+</From>)<To>(?:<User FriendlyName=".*?"/>)+</To><Text(?: Style="(.*?)")?>(.*?)</Text></Message>|;     my $F = join '<br />', ...

Perl Net::LDAP::SimpleServer

Adaptaciones sobre el módulo LDAP Server para Windows (Strawberry Perl) Lista de adaptaciones (continúa más abajo): - Relajación de condiciones de bind:     - Cuenta principal (principal account)     - Validación de contraseñas Ubicación del archivo: %Strawberry_Perl%\site\lib\net\ldap\SimpleServer\ProtocolHandler.pm CPAN: http://search.cpan.org/~russoz/Net-LDAP-SimpleServer-0.0.17/lib/Net/LDAP/SimpleServer.pm Código: package Net::LDAP::SimpleServer::ProtocolHandler; use strict; use warnings; # ABSTRACT: LDAP protocol handler used with Net::LDAP::SimpleServer our $VERSION = '0.0.17';    # VERSION use Net::LDAP::Server; use base 'Net::LDAP::Server'; use fields qw(store root_dn root_pw allow_anon); use Carp; use Net::LDAP::LDIF; use Net::LDAP::Util qw{canonical_dn}; use Net::LDAP::FilterMatch; use Net::LDAP::Constant (     qw/LDAP_SUCCESS LDAP_AUTH_UNKNOWN LDAP_INVALID_CREDENTIALS/,   ...