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

161
Vistas
Problema de cierre de React y JS

Antecedentes del problema

Tengo una clase "Ticker" simple que puede contener una única devolución de llamada y ejecutar esa devolución de llamada cada ~1s a través setInterval El código es el siguiente.

 class Ticker{ listner = null; constructor(){ setInterval(this.excuteCallbackInterval, 1000) } addListner(callback){ this.listner = callback } excuteCallbackInterval = () => { if(this.listner){ this.listner(); }else { console.log("no listner registered"); } } }

Tengo un React Functional Component en otro archivo, que crea una instancia de un objeto Ticker, a nivel de clase (es decir, fuera del componente funcional) pero dentro del mismo archivo. Aquí está el código para ese componente. (algunas partes se eliminan para que sea conciso)

 . . . const ticker = new Ticker() // react component. function TimerDuration({ changingValue }) { const unsubscribe = useRef(null) function runEachSecond() { console.log('inside runEachSecond', changingValue) } useEffect(() => { unsubscribe.current = ticker.addListener(runEachSecond) // Cleanup return () => { try { unsubscribe.current() } catch (err) { // Do nothing } } }, []) return ( <Text> {changingValue} </Text> ) }

Problema

Mi problema es que cuando el temporizador TimerDuration muestra inicialmente changingValue pintado en la pantalla y excuteCallbackInterval changingValue el mismo,

Pero cuando se actualiza la propiedad ChangingValue, ese valor actualizado no se refleja dentro excuteCallbackInterval pero el changingValue se refleja en el valor pintado en la pantalla.

Solución.

Mi solución fue (en cierto modo por instinto) almacenar el valor de changingValue en una referencia y actualizarlo dentro de un segundo useEffect que se ejecuta cada vez. Puede que no sea el ideal, de ahí esta pregunta.

Pregunta

Mi pregunta es ¿por qué estoy viendo este comportamiento? runEachSecond se evalúa con cada actualización de prop. Y puede acceder a changingValue porque está en su ámbito principal. La función excuteCallbackInterval dentro del Ticker también tiene acceso a changingValue debido al cierre. Pero, ¿por qué la actualización no se refleja en excuteCallbackInterval ? También hay una mejor manera de resolver este problema?

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Mi pregunta es ¿por qué estoy viendo este comportamiento? runEachSecond se evalúa con cada actualización de prop.

No, no está actualizado. En React, todas las variables permanecen constantes. Se crea una nueva función runEachSecond cada vez que se procesa el componente de la función TimerDuration , y esa nueva función se cerraría sobre el nuevo parámetro changingValue .

Sin embargo, runEachSecond solo se usa en el efecto (en ticker.addListener(runEachSecond) ), que se ejecuta solo una vez (cuando el componente está montado). El ticker almacenará solo la primera de las muchas funciones runEachSecond , y nunca cambiará (no se vuelve a llamar a addListener ), y esa primera función aún se cierra sobre el primer changingValue .

Solo quiero que se suscriba después del montaje y se dé de baja al desmontarlo.

En ese caso, debe almacenar el valor changingValue en la referencia y luego consultar esa referencia (y sus valores futuros) desde la función de escucha de ticker. La referencia para la función de cancelación de unsubscribe devuelta por addListener no es necesaria.

 function TimerDuration({ changingValue }) { const value = useRef(null); value.current = changingValue; //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ useEffect(() => { const unsubscribe = ticker.addListener(function runEachSecond() { console.log('inside runEachSecond', value.current); // ^^^^^^^^^^^^^ }); // Cleanup return () => { try { unsubscribe(); } catch (err) { // Do nothing } } }, []) return ( <Text> {changingValue} </Text> ) }
about 4 years ago · Juan Pablo Isaza Denunciar

0

Quiere darse de baja y volver a suscribirse cada vez que changingValue el valor. O, dicho de otra manera: desea actualizar la devolución de llamada del ticker para evitar que se vuelva obsoleto.

 useEffect(() => { function runEachSecond() { console.log('inside runEachSecond', changingValue) } const unsubscribe = ticker.addListener(runEachSecond) // Cleanup return () => { try { unsubscribe() } catch (err) { // Do nothing } } }, [changingValue]) // see changingValue in the deps

¿Por qué necesitas hacer esto? En este momento, su componente hace algo como esto:

  • montar
  • se crea runEachSecond (instancia #1)
  • suscríbase a Ticker, pase runEachSecond #1
  • changingValue de valor prop obtener actualización
  • runEachSecond se crea de nuevo (instancia #2)
  • Ticker todavía tiene una referencia de runEachSecond #1

Después de agregar ChangingValue en las dependencias de changingValue :

  • montar
  • se crea runEachSecond (instancia #1)
  • suscríbase a Ticker, pase runEachSecond #1
  • changingValue de valor prop obtener actualización
  • runEachSecond se crea de nuevo (instancia #2)
  • Ticker darse de baja de runEachSecond #1
  • Ticker suscríbase de nuevo, pero para runEachSecond #2
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