【发布时间】:2020-03-28 21:39:31
【问题描述】:
简介 我在 create-react-app 应用程序中有一个用户输入元素。它允许用户键入一个数字,或使用箭头向上或向下增加数字。然后输出显示这个数字。
问题 用户想要到达某个数字,无论他们如何输入数字,都会有虚假的中间值触发 onChange 事件监听器。 如果用户尝试用键盘输入“15”,输出首先是“1”,然后是“15”,但我希望它只是“15”。我不想使用按钮/提交/等或其他事件。 如果用户按住从 0 到 500 的向上箭头,我想在“快速变化”输入减慢/停止后直接更新到 500。
目标 我想编写一个 onChange 函数,以便仅当 onChange not 自上次事件以来触发事件至少 600 毫秒时才更新输出。
详情 如果用户键入“1”然后键入“5”(表示“15”)的间隔小于 600 毫秒,则输出应更新为“15”,并跳过“1”。但是,如果用户在输入“1”和“5”之间花费的时间超过 600 毫秒,那么输出应该首先是“1”,然后是“5”。同样,如果用户上下快速按下增量箭头,则输出不应该更新,直到它们停止或减速。
在终端中,使用 create-react-app 制作一个 react 应用
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;
【问题讨论】:
-
如果我理解正确,我想你会想要去抖动:lodash.com/docs/4.17.15#debounce 你的函数。这将延迟调用回调函数,直到经过设定的时间(700 毫秒)。
-
@MattCarlotta 我用过 lodash,但从不反跳 - 我会调查一下,谢谢。
-
很确定 lodash 的去抖动功能会如你所愿。试一试,如果您仍然需要帮助,我将创建一个有效的代码框示例。
-
@MattCarlotta 是的,去抖成功了!花了这么多时间试图让自己去抖动!您想回答这个问题以便我接受吗?如果没有,我可以提出答案。
-
继续为可能遇到相同问题的人提供解决方案。
标签: reactjs input settimeout setinterval onchange