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
相关产品推荐
相关产品推荐

