为什么 Native DOM 事件总是重置 React Component 状态

Why Native DOM event always reset React Component state

我知道合成事件,而不是原生dom事件,应该是处理的方式React App 中的交互,但我想知道为什么这种行为如此奇怪。当 React 事件正常运行时,dom 事件总是将状态重置为初始状态。

import React, { useState, useEffect } from "react";
import "./style.css";

export default function App() {
  const [num, setNum] = useState(0);
  function clickMe() {
    setNum(num + 1);
  }
  useEffect(() => {
    document.getElementById("app_btn").addEventListener("click", clickMe);
    return () =>
      document.getElementById("app_btn").removeEventListener("click", clickMe);
  }, []);
  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <div>App {num}</div>
      <button id="app_btn">DOM click</button> <br />
      <button onClick={clickMe}>React Click</button>
    </div>
  );
}

完整的项目可以在这里打开https://stackblitz.com/edit/react-wqrmcu?file=src/App.js

发生这种情况是因为您的本机事件处理程序仍会关闭首次呈现后可用的 num 值(该值为 0)。您需要在每个状态更新时添加和删除本机事件侦听器才能像这样工作:-

  useEffect(() => {
    document.getElementById("app_btn").addEventListener("click", clickMe);
    return () =>
      document.getElementById("app_btn").removeEventListener("click", clickMe);
  }, [num]);

正如@Mahdi 指出的那样,另一种方法可能是在状态更新器函数中使用回调。这将允许您在先前状态的基础上获得新状态。但是本机事件侦听器可访问的 num 的值仍然为 0。您可以通过在 clickMe.

中执行 console.log(num) 来验证这一点
function clickMe() {
    setNum(prevNum => prevNum + 1); // <-- you need this
  }