如何在 EventHandler 中使用状态变量 (useState)

How to use State Variable (useState) in an EventHandler

我有一个 React 功能组件,它从 useState() 接收一个带有变量的道具。这工作正常,但如果我在 EventListener 中使用它,它不会得到更新。我尝试了以下但仍然无效。

也许有人可以解释原因。

谢谢

我希望 x 是更新后的数字,但它始终具有 EventHandler 初始设置的值。

import React, { useState, useEffect } from "react";
import ReactDom from "react-dom";

const App = () => {
   const [num, setNum] = useState(50);

  return (
    <div>
       <button onClick={() => setNum(prev => prev + 1)}>Test</button>
       <div>{num}</div>
       <Child num={num} />
    </div>
  );
};

const Child = ({ num }) => {
  let x = 0;
  const md = () => {
  console.log(num, x);
};

useEffect(() => {
x = num;
  }, [num]);

useEffect(() => {
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, []);

  return <div id="box">click {num}</div>; 
};

ReactDom.render(<App />, document.getElementById("app"));

您的 Child 的每次渲染都会得到一个新的 x、一个新的 props 对象等。但是您只绑定了一次事件侦听器,因此仅捕获初始的props.num 值。

两种修复方式:

num 改变时重新绑定事件侦听器,通过将 num 作为依赖项传递给您的效果以绑定事件侦听器:

const Child = ({ num }) => {

  useEffect(() => {
    // no need to define this in main function since it is only
    // used inside this effect
    const md = () => { console.log(num); };
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, [num]);

  return <div id="box">click {num}</div>; 
};

或者使用 ref 来保存 num 的值并将您的事件侦听器绑定到 ref。这为您提供了一个间接级别来处理更改:

const Child = ({ num }) => {
  const numRef = useRef();  // will be same object each render
  numRef.current = num; // assign new num value each render

  useEffect(() => {
    // no need to define this in main function since it is only
    // used inside this effect
    // binds to same ref object, and reaches in to get current num value
    const md = () => { console.log(numRef.current); };
    document.getElementById("box").addEventListener("mousedown", md);

    return () => {
      document.removeEventListener("mousedown", md);
    };
  }, []);

  return <div id="box">click {num}</div>; 
};