Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

267
Vistas
React/Redux, useEffect/useSelector, cierres obsoletos y detectores de eventos

Tengo un componente de clase React/Redux que estoy convirtiendo en un componente funcional.

Anteriormente, tenía una devolución de llamada de componentDidMount que agregaba un detector de eventos para un evento personalizado enviado desde otra parte de la aplicación. Esto está siendo reemplazado por useEffect . El detector de eventos, al activarse, llama a un método en otro lugar de este componente.

Este método realiza acciones que dependen de los valores recuperados de un selector. Inicialmente, estaba pasando useEffect una matriz vacía de dependencias para que solo agregara el detector de eventos en el montaje. Sin embargo, obviamente esto da como resultado un cierre obsoleto en torno a los valores del selector. Una solución funcional es pasarle el selector como una dependencia; sin embargo, esto da como resultado que el oyente se elimine/vuelva a agregar cada vez que cambie el valor del selector, lo cual no es bueno.

Estoy tratando de pensar en una solución que solo agregue el detector de eventos una vez y permita que el método llamado acceda al valor actual del selector.

Código de ejemplo:

 const currentValue = useSelector(state => getValue(state)); useEffect(() => { document.addEventListener('my.custom.event', handleEvent); return(() => document.removeEventListener('my.custom.event', handleEvent)); }, []); const handleEvent = () => { console.log(currentValue) }

Tal como está, esto crea un cierre obsoleto en torno a currentValue de modo que, en el desencadenante del evento, el valor registrado no es necesariamente el más reciente.

Cambiar [] a [currentValue] en useEffect da como resultado el comportamiento esperado, pero elimina/vuelve a agregar el detector de eventos en cada cambio de currentValue .

Dado que este no es un valor de estado del componente, no hay opción para usar una devolución de llamada como console.log(currentValue => console.log(currentValue)) para acceder al valor más reciente. También jugué con el uso de useRef para mantener el valor, pero creo que necesitaría alguna forma de actualizar el valor de referencia cada vez que cambia el valor del selector, lo cual no es una gran solución.

En el componente real, el valor de currentValue se modifica en Redux por otros componentes, por lo que cambiarlo a un valor de estado tampoco es viable.

Me pregunto:

  • si hay una solución para actualizar el valor del selector en el método llamado;
  • si la única solución es eliminar/volver a agregar el oyente en el cambio de dependencia, o;
  • si es mejor dejar este componente como un componente de clase y omitir este problema por completo ( componentDidMount no sufre el problema de cierre obsoleto).
about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

El método useRef suele ser la solución para este problema, pero necesitará otro useEffect para actualizar la referencia con el currentValue :

 const currentValue = useSelector(state => getValue(state)); const valueRef = useRef(); useEffect(() => { valueRef.current = currentValue; }, [currentValue]); useEffect(() => { const handleEvent = () => { console.log(valueRef.current) } document.addEventListener('my.custom.event', handleEvent); return(() => document.removeEventListener('my.custom.event', handleEvent)); }, []);

Sin embargo, también puede extraer la función completa de useEffect y usarla en un enlace, de modo que pueda crear fácilmente un enlace personalizado para el manejo de eventos:

 const useEventHandler = (eventName, eventHandler, eventTarget = document) => { const eventHandlerRef = useRef(); useEffect(() => { eventHandlerRef.current = eventHandler; }); useEffect(() => { const handleEvent = (...args) => eventHandlerRef?.current(...args); eventTarget.addEventListener(eventName, handleEvent); return (() => eventTarget.removeEventListener(eventName, handleEvent)); }, []); }

Usando el gancho:

 const currentValue = useSelector(state => getValue(state)); useEventHandler('my.custom.event', () => console.log(currentValue))
about 4 years ago · Juan Pablo Isaza Denunciar

0

sin embargo, esto da como resultado que el oyente se elimine o vuelva a agregar cada vez que cambie el valor del selector, lo cual no es muy bueno.

Por qué es un problema? ¿Afecta el rendimiento de su aplicación de alguna manera medible? Desde el punto de vista de la inmutabilidad, si el valor cambia, entonces el detector de eventos hace algo diferente, por lo que tiene sentido simplemente reemplazar el detector de eventos por uno diferente.

Si el valor cambia muchas veces por segundo (por ejemplo, en cada cuadro o cada movimiento del mouse), entonces crea un pequeño impacto en el rendimiento, en cuyo caso la solución de Ori Drori podría ser buena, pero hace que el código sea más difícil de entender y el la ganancia de rendimiento es bastante pequeña.

Pero si el valor solo cambia unas pocas veces por segundo o con menos frecuencia, no me preocuparía en absoluto por agregar y eliminar el detector de eventos.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda