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