【问题标题】:how to debounce a final-form Field?如何去抖动最终形式的字段?
【发布时间】:2019-12-11 06:02:09
【问题描述】:
【问题讨论】:
标签:
reactjs
throttling
debouncing
react-final-form
final-form
【解决方案1】:
首先,我鼓励您在不使用模糊的包层的情况下完成所有这些操作。这将帮助您真正了解流程,但是,以下是在输入更改时调用函数的方法:
- 去抖动(仅在用户停止输入 500 毫秒时执行一次)
- 节流(批处理然后每 500 毫秒执行一次)
- 正常(在每次输入更新时执行)
在这种情况下,我只是在渲染方法之外创建了一个去抖动函数。这在使用类而不是钩子时会有所不同:
钩子:
const handleSearch = debounce(searchText => { ... }, 500);
类(或者您可以在constructor 中对类字段进行去抖动,都可以):
class Example extends Component {
handleSearch = debounce(searchText => { ... }, 500)
render = () => { ... }
}
工作示例(在代码框控制台打开时输入):
去抖动、节流和正常执行的区别:
同上,减去 react-final-form 和 react-final-form-listeners(项目中的依赖项少了两个!):
工作示例(在代码框控制台打开时输入):
【解决方案2】:
您的解决方案存在多个问题:
- 使用 lodash
debounce 而不是 throttle。
- 在表单外部创建去抖动函数,以防止在每次重新渲染或更改时重新分配它
- 调用表单提交操作,而不是提交处理程序
handleSubmit
修改并运行您的示例:
【解决方案3】:
这是一个记忆的去抖版本:
export default function DebouncedMemoizedField({
milliseconds = 400,
validate,
...props
}) {
const timeout = useRef(null);
const lastValue = useRef(null);
const lastResult = useRef(null);
const validateField = (value, values, meta) => new Promise((resolve) => {
if (timeout.current) {
timeout.current();
}
if (value !== lastValue.current) {
const timerId = setTimeout(() => {
lastValue.current = value;
lastResult.current = validate(value, values, meta);
resolve(lastResult.current);
}, milliseconds);
timeout.current = () => {
clearTimeout(timerId);
resolve(true);
};
} else {
resolve(lastResult.current);
}
});
return <Field validate={validateField} {...props} />;
}
用法:
<MemoizedDebouncedValidationField
name="username"
validate={(value) => (value === 'jim' ? 'Username exists' : undefined)}
render={({ input, meta }) => (
<>
<input {...input} />
{(meta.touched && meta.error) && <p>Error</p>}
</>
)}
/>