Listener de eventos agregado múltiples veces en JavaScript, causando problemas de rendimiento

Resumen del Problema: Múltiples Añadidos de Event Listener en JavaScript

En el desarrollo de aplicaciones web, es común encontrarse con problemas relacionados con la eficiencia del código. Un caso frecuente es la adición múltiple de event listeners, lo cual puede causar problemas de rendimiento. Este resumen aborda la situación específica donde se añade un event listener de dblclick a elementos con la clase .ag-header-cell-resize, resultando en múltiples instancias de este listener cada vez que el componente se actualiza o se vuelve a renderizar.

Problema Identificado

Al agregar un listener para el evento dblclick a los elementos deseados, este se añade múltiples veces. El código actual para este propósito se muestra a continuación:

const resizeElements = document.querySelectorAll('.ag-header-cell-resize');

resizeElements.forEach((element) => {
    element.addEventListener('dblclick', (event) => {
        const parentHeaderCell = event.target?.closest('.ag-header-cell');
        if (parentHeaderCell) {
            const colId = parentHeaderCell.getAttribute('col-id');
            console.log('Column ID:', colId);

            const column = updateColumnWidth(tableColumns, colId);
            setTableColumns(column);
        }
    });
});

Intentos de Solución

Se han explorado varias estrategias para mitigar el problema, pero ninguna ha resultado fructífera:

  1. Uso de { once: true }: Aunque previene la duplicación del listener, solo permite que se ejecute una vez por elemento, lo cual no es el comportamiento deseado.

  2. Eliminar el event listener antes de añadirlo: Esto no funciona, ya que cada referencia al handler es única en cada ciclo.

  3. Uso de useEffect en React: A pesar de implementar la limpieza del listener, aún persiste la duplicación.

Solución Propuesta

Para asegurar que cada event listener se añada solo una vez por elemento y no se repita en cada renderizado, se puede adoptar la siguiente estrategia:

  • Comprobar si el listener ya está presente: Utilizar un método que verifique si el listener ya se ha añadido o mantener un estado para evitar la duplicación.

Aquí te presento un enfoque mejorado utilizando useEffect:

import React, { useEffect } from 'react';

const MyComponent = () => {
    const handleResize = (event) => {
        const parentHeaderCell = event.target?.closest('.ag-header-cell');
        if (parentHeaderCell) {
            const colId = parentHeaderCell.getAttribute('col-id');
            console.log('Column ID:', colId);
            const column = updateColumnWidth(tableColumns, colId);
            setTableColumns(column);
        }
    };

    useEffect(() => {
        const resizeElements = document.querySelectorAll('.ag-header-cell-resize');

        const addListeners = () => {
            resizeElements.forEach((element) => {
                if (!element.listenerAdded) { // Comprobación personalizada
                    element.addEventListener('dblclick', handleResize);
                    element.listenerAdded = true; // Marcamos el listener como añadido
                }
            });
        };

        addListeners();

        return () => {
            resizeElements.forEach((element) => {
                element.removeEventListener('dblclick', handleResize);
                delete element.listenerAdded; // Limpieza
            });
        };
    }, []);

    return (
        // ... tu codigo JSX aqui
    );
};

export default MyComponent;

Conclusión

Este enfoque ayuda a asegurar que el event listener dblclick se añada solo una vez a cada elemento y previene duplicaciones, mejorando así el rendimiento del aplicativo. Al marcar cada elemento con una propiedad que verifica si el listener ya ha sido añadido, se logra mantener un control efectivo sobre los listeners en un contexto dinámico como React.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *