Tengo problemas para que la función "establecer" de useState funcione como necesito. Me gustaría poder usar un oyente de teclado para incrementar un contador, pero aunque la función keyListener se está ejecutando, selection no pasa de 1.

¿Es este un problema de actualización asincrónica?

Para demostrar mi problema, hice el siguiente proyecto de falla. (Para usar, haga clic en el fondo amarillo y presione las teclas para incrementar el contador de selección).

import React, { useState } from 'react';

function App() {
  const [selection, setSelection] = useState(0)
  
  const attachKeyListener = () => { 
    console.log("attaching listener")
    document.addEventListener("keydown", keyListener) 
  };
  
  const keyListener = (e) => {
    console.log("increasing selection")
    let tmp = selection + 1
    setSelection(tmp)
  };

  return (
    <div className="App" onClick={attachKeyListener} style={{background:"yellow"}}>
      Counter: {selection} 
    </div>
  );
}

export default App;

Ejemplo en vivo: https://gaudy-brave-tenor.glitch.me

0
Phil Brockman 23 ene. 2021 a las 06:29

1 respuesta

La mejor respuesta

Actualmente, está adjuntando un nuevo oyente cada vez que se hace clic en el div. En su lugar, agregue el oyente solo una vez , en el montaje inicial, y use el formulario de devolución de llamada para asegurarse de tener el selection actualizado al configurar nuevamente:

function App() {
  const [selection, setSelection] = React.useState(0)
  React.useEffect(() => {
    console.log("attaching listener")
    const keyListener = (e) => {
      console.log("increasing selection")
      let tmp = selection + 1
      setSelection(selection => selection + 1)
    };
    document.addEventListener("keydown", keyListener) 
  }, []);
  
  return (
    <div className="App" style={{background:"yellow"}}>
      Counter: {selection} 
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
1
CertainPerformance 23 ene. 2021 a las 03:33