Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

162
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda