reactjs - 仅在 onChange 停止触发设定时间后,如何使 React 输入 onChange 设置状态?
问题描述
简介 我在 create-react-app 应用程序中有一个用户输入元素。它允许用户键入一个数字,或使用箭头向上或向下增加数字。然后输出显示这个数字。
问题 用户想要到达某个数字,无论他们如何输入数字,都会有虚假的中间值触发 onChange 事件监听器。如果用户尝试用键盘输入“15”,输出首先是“1”,然后是“15”,但我希望它只是“15”。我不想使用按钮/提交/等或其他事件。如果用户按住从 0 到 500 的向上箭头,我想在“快速变化”输入减慢/停止后直接更新到 500。
目标我想编写一个 onChange 函数,以便仅当 onChange自上次事件以来至少 600 毫秒未触发事件 时才更新输出。
详细信息 如果用户键入“1”然后键入“5”(表示“15”)的间隔小于 600 毫秒,则输出应更新为“15”,并跳过“1”。但是,如果用户在输入“1”和“5”之间花费的时间超过 600 毫秒,那么输出应该首先是“1”,然后是“5”。同样,如果用户上下快速按下增量箭头,则输出不应该更新,直到它们停止或减速。
在终端中,使用 create-react-app 创建一个反应应用程序
create-react-app delay-output-app
复制代码 并将其粘贴到 delay-output-app/src/App.js 中,替换所有以前的代码。
import React, { useState, useEffect, useRef } from "react";
import "./App.css";
function App() {
const inputRef = useRef();
const [userValue, setUserValue] = useState(0);
const [output, setOutput] = useState(0);
const updateOutput = () => {
setUserValue(inputRef.current.value);
setOutput(inputRef.current.value);
//if input is changing quickly - do not update output
//only update output if input has not changed for 700ms since last change.
};
return (
<div className="App">
<br></br>
<div>
<h1>Input</h1>
<input
ref={inputRef}
value={userValue}
type="number"
onChange={updateOutput}
></input>
</div>
<br></br>
<div>
<h1>Output</h1>
{output}
</div>
</div>
);
}
export default App;
在终端中运行应用程序...
cd delay-output-app
npm start
我尝试过使用 setTimeout 和 setInterval,但我一直遇到问题,尤其是与 react useEffect 挂钩时。同样,我不想使用按钮或让用户除了输入数字或单击箭头来更新输出之外需要按任何东西。只有输入值之间的时间决定了输入值何时是中间值或应该更新输出。
更新以包括去抖动- 我的印象是去抖动不应该在输入事件结束之前运行,但我仍然在等待期之后获得更新输出,无论用户输入事件是否结束。
带有 lodash debounce 的代码
import React, { useState, useRef } from "react";
import "./App.css";
import _ from "lodash";
function App() {
const inputRef = useRef();
const [userValue, setUserValue] = useState(0);
const [output, setOutput] = useState(0);
const updateOutput = _.debounce(
() => setOutput(inputRef.current.value),
700
);
//if input is changing quickly - do not update output
//only update output if input has not changed for 700ms since last change.
const updateUserValue = () => {
setUserValue(inputRef.current.value);
};
return (
<div className="App">
<br></br>
<div>
<h1>Input</h1>
<input
ref={inputRef}
value={userValue}
type="number"
onChange={() => {
updateOutput();
updateUserValue();
}}
></input>
</div>
<br></br>
<div>
<h1>Output</h1>
{output}
</div>
</div>
);
}
export default App;
解决方案
你真的不需要 ref 来解决这个问题。一个电话就useEffect
足够了:
useEffect(() => {
const timeout = setTimeout(() => {
setOutput(userValue);
}, 600);
return () => {
clearTimeout(timeout);
};
}, [userValue]);
const updateOutput = (e) => {
setUserValue(e.target.value);
};
推荐阅读
- java - SonarQUBE 和 compareTo 日期
- c# - 如何通过坐标更改导入的 STL 文件的位置
- javascript - 无法从 ibm-watson IamTokenManager 获取身份验证令牌
- odoo - 如何在 Odoo14 中存储登录用户
- python - 我的 tensorflow 没有检测到我的 gpu 并使用我的 cpu(机器学习)
- xapi - 如何将包含一些交互的 xAPI 语句写入问题页面
- c# - 如何在参数化查询中传递模式名称
- karate - 空手道 API:在 Json 有效负载空手道 API 中将数字舍入到小数点后 2 位
- python - 将区域合并为一个时,为什么不保留地理图的比例?
- jmeter - 在 JMeter 命令行之后执行的其他命令失败