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

131
Visualizações
Misma lógica pero diferente comportamiento en 'clase' y en 'componente funcional'

Intenté traducir un código de ejemplo de class a functional component y enfrenté el problema.

el archivo de destino está en components/Wheel/index.js

Función clave que causa el problema

 const selectItem = () => { if (selectedItem === null) { const selectedItem = Math.floor(Math.random() * items.length); console.log(selectedItem); setSelectedItem(selectedItem); } else { setSelectedItem(null); let t= setTimeout(() => { selectItem() }, 500); clearTimeout(t); } };

La primera vez es normal, a partir de la segunda vez, se necesitan 2 clics para que la rueda gire. Tuve que agregar clearTimeout() o se generó un bucle infinito , pero no sucede lo mismo en el original.

Ejemplo de trabajo original en class

Demostración de Codesandbox

Mi versión en functional component .

Mi version

Gracias.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Qué excelente matiz de ganchos que has descubierto. Cuando llama a selectItem en el tiempo de espera, el valor de selectedItem que se captura en el ámbito léxico es el último valor (no nulo).

Hay dos respuestas, una respuesta simple y una mejor respuesta de trabajo.

La respuesta simple es que puede lograrlo simplemente separando las funciones: https://codesandbox.io/s/spinning-wheel-game-forked-cecpi

Se parece a esto:

 const doSelect = () => { setSelectedItem(Math.floor(Math.random() * items.length)); }; const selectItem = () => { if (selectedItem === null) { doSelect(); } else { setSelectedItem(null); setTimeout(doSelect, 500); } };

Ahora, sigue leyendo si te atreves.

La respuesta complicada corrige la solución del problema si items.length puede cambiar entre el momento en que se configura un temporizador y se dispara:

https://codesandbox.io/s/spinning-wheel-game-bifurcado-wmeku

Volver a renderizar (es decir, configurar el estado) en un tiempo de espera causa complejidad: si el componente se volvió a renderizar entre el tiempo de espera, entonces su devolución de llamada podría haber capturado accesorios/estado "obsoletos". Así que están pasando muchas cosas aquí. Intentaré describirlo lo mejor que pueda:

 const [selectedItem, setSelectedItem] = useState(null); // we're going to use a ref to store our timer const timer = useRef(); const { items } = props; // this is just the callback that performs a random select // you can see it is dependent on items.length from props const doSelect = useCallback(() => { setSelectedItem(Math.floor(Math.random() * items.length)); }, [items.length]); // this is the callback to setup a timeout that we do // after the user has clicked a "second" time. // it is dependent on doSelect const doTimeout = useCallback(() => { timer.current = setTimeout(() => { doSelect(); timer.current = null; }, 500); }, [doSelect]); // Here's the tricky thing: if items.length changes in between // the time we rerender and our timer fires, then the timer callback will have // captured a stale value for items.length. // The way we fix this is by using this effect. // If items.length changes and there is a timer in progress we need to: // 1. clear it // 2. run it again // // In a perfect world we'd be capturing the amount of time remaining in the // timer and fire it exactly (which requires another ref) // feel free to try and implement that! useEffect(() => { if (!timer.current) return; clearTimeout(timer.current); doTimeout(); // it's safe to ignore this warning because // we know exactly what the dependencies are here }, [items.length, doTimeout]); const selectItem = () => { if (selectedItem === null) { doSelect(); } else { setSelectedItem(null); doTimeout(); } };
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