为什么 React 在 useState 中使用了错误的值?

Why is React using the wrong value in useState?

我有一个像这样的 React 组件:

https://codepen.io/darajava/pen/NWrdWeP?editors=0010

function TestUseState() {
  const [count, setCount] = useState(0);
  const buttonRef = useRef(null);

  useEffect(() => {
    buttonRef.current.addEventListener("click", () => {
      alert(count);
    });

    setCount(10000);
  }, []);
  
  return (
    <div ref={buttonRef}>
      Click
    </div>
  )
}

我在按钮上设置了一个事件监听器,它似乎取状态的初始值,之后直接设置它。这是预期的行为吗?我怎样才能避免这种情况?

有问题的实际代码(无效,仅添加了相关部分):

const Game = () => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [player, setPlayer] = useState<IPlayer>();

  const setPosition = (newPos) => {
    console.log(player); // <--- player is undefined on mousemove
  };

  useEffect(() => {
    canvas = canvasRef.current;
    ctx = canvas.getContext('2d');
    
    canvas.addEventListener('mousemove', (e: MouseEvent) => {
      setPosition(getCursorPosition(canvas, e));
    });
  }, []);


  return (
    <canvas ref={canvasRef} styleName="canvas" />
  );
}

是的,这是预料之中的,但我能理解为什么它看起来很奇怪。

当您在 useEffect 挂钩中添加 ref 时,您将关闭 count 的值并将其保存以备后用,因此当您单击 sub 时,它会显示组件初始化时的值。

如果想提醒count的实际值可以在div后面加上onClick={()=>alert(count)},这样也比较符合React的声明式

不鼓励您在 React 中使用 refs,因为 React 维护一个虚拟 dom。当您需要直接访问 dom 个元素时,您可以使用 refs。

编辑:您也可以将其用于鼠标移动事件:

https://reactjs.org/docs/events.html#mouse-events

在功能组件的主体中单独编写处理函数,并将其传递给 canvas 元素的 onMouseMove 属性。