You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React按下Enter触发函数时获取过时状态的问题

React + MobX + MaterialUI 状态变量异常问题
  • 触发场景差异:点击按钮调用handleSendPing时,selectedUser等状态变量能正确转换为NewPingDto对象;按Enter键触发该函数时,对象的recipient、locationName、pingMessage字段为空,但控制台单独打印的状态值是正确的。
  • 排除情况:页面无表单元素,所有按钮均设置type="button",可排除意外提交导致的状态重置。

相关代码

useEffect(() => {
  window.addEventListener("keydown", handleKeyPress);
  return () => {
    window.removeEventListener("keydown", handleKeyPress);
  };
}, []);
const handleKeyPress = (e: any) => {
  if (e.key === "Enter") {
    e.preventDefault();
    handleSendPing();
  }
};
const handleSendPing = () => {
  if (userStore.user) {
    var ping: NewPingDto = {
      recipient: selectedUser,
      locationName: selectedLocation,
      pingMessage: selectedPingMessage,
      senderId: userStore.user.id,
      companyId: userStore.user.companyId,
      dateCreated: new Date(),
      dateLastModified: new Date(),
      isExpired: false,
      isUrgent: urgentPing,
      pingResponse: "",
      isRead: false,
    };
    console.log("foo", ping);
    pingStore.addPing(ping);
  }
};
useEffect(() => {
  console.log("new selectedUser", selectedUser);
}, [selectedUser]);

Enter触发时的输出结果

{
  "recipient": "",
  "locationName": "",
  "pingMessage": "",
  "senderId": "c0a0d5a0-ffaf-4b7e-8f4a-6b6b8b7b8b71",
  "companyId": 1,
  "dateCreated": "2023-08-21T17:39:25.014Z",
  "dateLastModified": "2023-08-21T17:39:25.014Z",
  "isExpired": false,
  "isUrgent": false,
  "pingResponse": "",
  "isRead": false
}

问题原因

绑定window键盘事件的useEffect依赖数组为空,组件挂载后仅执行一次事件绑定。此时handleKeyPress函数内部引用的selectedUser等状态变量是组件初始渲染时的值(空字符串),后续状态更新时不会重新绑定事件,导致按Enter触发时仍使用旧的状态值。

解决方法

方案1:更新事件绑定的依赖,确保回调引用最新状态

将handleKeyPress定义在useEffect内部,并把handleSendPing加入依赖数组,每次handleSendPing更新时重新绑定事件:

useEffect(() => {
  const handleKeyPress = (e: any) => {
    if (e.key === "Enter") {
      e.preventDefault();
      handleSendPing();
    }
  };
  window.addEventListener("keydown", handleKeyPress);
  return () => {
    window.removeEventListener("keydown", handleKeyPress);
  };
}, [handleSendPing]);

方案2:用useCallback稳定handleSendPing的引用

给handleSendPing加上useCallback包裹,明确它的依赖项,避免不必要的重新创建,同时确保事件回调能获取最新的状态值:

const handleSendPing = useCallback(() => {
  if (userStore.user) {
    var ping: NewPingDto = {
      recipient: selectedUser,
      locationName: selectedLocation,
      pingMessage: selectedPingMessage,
      senderId: userStore.user.id,
      companyId: userStore.user.companyId,
      dateCreated: new Date(),
      dateLastModified: new Date(),
      isExpired: false,
      isUrgent: urgentPing,
      pingResponse: "",
      isRead: false,
    };
    console.log("foo", ping);
    pingStore.addPing(ping);
  }
}, [userStore.user, selectedUser, selectedLocation, selectedPingMessage, urgentPing, pingStore]);

两种方案结合使用,即可解决按Enter触发时状态变量为空的问题。

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 19:09:55