Saltar al contenido

React Hooks useState+useEffect+event da un estado obsoleto

Posterior a mirar en diversos repositorios y foros de internet al terminar nos hemos encontrado la respuesta que te compartimos ahora.

Solución:

value está obsoleto en el controlador de eventos porque obtiene su valor del cierre donde se definió. A menos que volvamos a suscribir un nuevo controlador de eventos cada vez value cambia, no obtendrá el nuevo valor.

Solución 1: haga que el segundo argumento tenga el efecto de publicación [value]. Esto hace que el controlador de eventos obtenga el valor correcto, pero también hace que el efecto se ejecute de nuevo con cada pulsación de tecla.

Solución 2: utilice un ref para almacenar lo último value en una variable de instancia de componente. Luego, haga un efecto que no haga más que actualizar esta variable cada vez value cambios de estado. En el controlador de eventos, use el ref, no value.

const [value, setValue] = useState(initialValue);
const refValue = useRef(value);
useEffect(() => 
    refValue.current = value;
);
const handleEvent = (msg, data) => 
    console.info("Value in event handler: ", refValue.current);
;

https://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often

Parece que hay otras soluciones en esa página que también podrían funcionar. Muchas gracias a @Dinesh por la ayuda.

Respuesta actualizada.

El problema no es con los ganchos. El valor de estado inicial se cerró y pasó a EventEmitter y se usó una y otra vez.

No es una buena idea usar valores de estado directamente en handleEvent. En su lugar, debemos pasarlos como parámetros mientras emitimos el evento.

import React,  useState, useEffect  from "react";
import  Controlled as CodeMirror  from "react-codemirror2";
import "codemirror/lib/codemirror.css";
import EventEmitter from "events";

let ee = new EventEmitter();

const initialValue = "initial value";

function App(props) 
  const [value, setValue] = useState(initialValue);
  const [isReady, setReady] = useState(false);

  // Should get the latest value
  function handleEvent(value, msg, data) 
    // Do not use state values in this handler
    // the params are closed and are executed in the context of EventEmitter
    // pass values as parameters instead
    console.info("Value in event handler: ", value);
    document.getElementById("result").innerHTML = value;
  

  // Get value from server on component creation (mocked)
  useEffect(() => 
    setTimeout(() => 
      setValue("value from server");
      setReady(true);
    , 1000);
  , []);

  // Subscribe to events on component creation
  useEffect(
    () => 
      if (isReady) 
        ee.on("some_event", handleEvent);
      
      return () => 
        if (!ee.off) return;
        ee.off(handleEvent);
      ;
    ,
    [isReady]
  );

  function handleClick(e) 
    ee.emit("some_event", value);
  

  return (
    
       
          setValue(newValue);
        
      />
      
      
); export default App;

Aquí hay una caja de códigos de trabajo

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *