Me encontré con este comportamiento. Dos onChange se llaman a su vez. Uno de ellos guarda datos en el estado y usa el estado anterior para generar uno nuevo.
const onChange = (data) => { setState1((prev) => { console.log("onChange set state"); return [...prev, data]; }); };El otro simplemente imprime algo en la consola.
const onChange2 = (data) => { console.log("onChange2"); };onChange y onChange2 llamados después de hacer clic en el botón
<button onClick={() => { onChange({ foo: "bar" }); onChange2(); }} > 2 </button>useEffect - guarda los datos en el estado
const [state, setState] = useState(0); const [state1, setState1] = useState([]); useEffect(() => { setState((prev) => { console.log("use effect set state"); return prev + 1; }); }, []);Entonces, si no usa useEffect (comentar), el registro de la consola, que en el primer onChange se llamará primero, luego el registro de la consola del segundo onChange
Si quita el comentario de useEffect, entonces la consola iniciará sesión desde onChange2 primero, luego desde onChange
¿Por qué sucede esto, quién puede decirlo?
CodeSandBox: https://codesandbox.io/s/eager-hooks-sczvb
El orden de llamada de onChange y onChange2 parece cambiar porque console.log in onChange está dentro de la devolución de llamada pasada a setState1 .
Si mueve el archivo console.log directamente en onChange , verá que el orden es el mismo con o sin useEffect .
const onChange = (data) => { console.log("onChange set state"); setState1((prev) => { return [...prev, data]; }); }; Es importante comprender que cuando llamas a setState no hay garantía de que el estado cambie de inmediato, depende de React decidir cuándo aplicar el nuevo estado y activar un nuevo renderizado.
Esta es la razón por la que la devolución de llamada pasada a setState solo debe devolver un nuevo estado y no ejecutar ningún efecto (como console.log ), ya que el momento en que se ejecuta este código se considera en los detalles de implementación y podría cambiar con cualquier versión de React.
El comportamiento esperado es onChange2 llamado primero, y onChange set state llamado segundo, cualquiera que sea el cuerpo useEffect que se comente. porque onChange2 llamó ahora mismo. pero onChange set state en setState fn llamado después de renderizado。
El "error" que se ve es por qué onChange set state llamado primero cuando se hace clic por primera vez. Hmm... encuentre reaccionar computeExpirationForFiber. La devolución de llamada de setState ejecuta sincronización o asíncrono según diferentes condiciones. Es difícil de leer.