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

React应用中OnKeyDown事件仅触发一次,多次按键无响应如何解决

问题原因

  • 光标区间判断逻辑错误:第一次按下快捷键后,你主动选中了日/月对应的文本区间,此时输入框的selectionStart等于区间起始值0或3,不满足原有代码中>0、>3的判断条件,后续按快捷键时逻辑不会执行,并不是onKeyDown事件没有触发。
  • 日期对象脱离React状态管理:你将cur_date定义在组件外部作为全局常量,所有修改直接操作这个可变对象,既不会触发组件的响应式更新,也容易出现状态不同步的问题。
  • 冗余状态未使用:代码中声明了currentDate状态但没有实际使用,状态管理逻辑混乱。

修复后代码

import React, { useState, useEffect, useRef } from "react";
import styles from "./DataInput.module.css";

const DataInput = () => {
  const inputEl = useRef();
  const [selection, setSelection] = useState();
  // 将日期存入React状态管理
  const [currentDate, setCurrentDate] = useState(new Date());

  // 从状态中的日期生成格式化字符串
  const formatDate = (date) => {
    return date
      .toLocaleString()
      .replaceAll(".", "/")
      .replace(",", "");
  };
  const [value, setValue] = useState(formatDate(currentDate));

  useEffect(() => {
    if (!selection) return; // 防止初始化时执行
    const { start, end } = selection;
    inputEl.current.focus();
    inputEl.current.setSelectionRange(start, end);
  }, [selection]);

  const keyHandler = (e) => {
    const selStart = inputEl.current.selectionStart;
    if (e.ctrlKey && e.key === "ArrowUp") {
      e.preventDefault();
      // 调整光标判断逻辑,覆盖选中场景
      if (selStart >= 0 && selStart <= 2) {
        setSelection({ start: 0, end: 2 });
        // 基于现有日期生成新日期,不直接修改原对象
        const newDate = new Date(currentDate);
        newDate.setDate(newDate.getDate() + 1);
        setCurrentDate(newDate);
        setValue(formatDate(newDate));
      }
      if (selStart >= 3 && selStart <= 5) {
        setSelection({ start: 3, end: 5 });
        const newDate = new Date(currentDate);
        newDate.setMonth(newDate.getMonth() + 1);
        setCurrentDate(newDate);
        setValue(formatDate(newDate));
      }
    }
    if (e.ctrlKey && e.key === "ArrowDown") {
      e.preventDefault();
      if (selStart >= 0 && selStart <= 2) {
        setSelection({ start: 0, end: 2 });
        const newDate = new Date(currentDate);
        newDate.setDate(newDate.getDate() - 1);
        setCurrentDate(newDate);
        setValue(formatDate(newDate));
      }
      if (selStart >= 3 && selStart <= 5) {
        setSelection({ start: 3, end: 5 });
        const newDate = new Date(currentDate);
        newDate.setMonth(newDate.getMonth() - 1);
        setCurrentDate(newDate);
        setValue(formatDate(newDate));
      }
    }
  };

  const changeHandler = (e) => {
    setValue(e.target.value);
  };

  return (
    <div className={styles.main}>
      <h1> Frontend Task</h1>
      <p id="name">Abramov David</p>
      <input
        ref={inputEl}
        value={value}
        onChange={changeHandler}
        onKeyDown={keyHandler}
      />
    </div>
  );
};

export default DataInput;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:54:02