Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

264
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!