如何去除最终形式的字段?

how to debounce a final-form Field?

这是一个很常见的查询,但我对新的 final-form 库有点困惑。我曾经使用 redux-form 但这个新版本太不一样了。

我的需求很简单,我想在用户输入一些文本时发送搜索,但我想在字段中添加一个 throttle

这是对库 react-final-form-listeners 的第一次尝试,但正如您将看到的,当您在文本字段中写入时,去抖不起作用:/

https://codesandbox.io/embed/react-final-form-simple-example-khkof

首先,我鼓励您在不使用模糊包层的情况下完成所有这些操作。这将帮助您真正理解流程,但是,当输入发生变化时,您可以通过以下方式调用函数:

  • debounce(仅在用户停止输入 500 毫秒时执行一次)
  • 节流(然后每 500 毫秒执行一次批处理)
  • 正常(在每次输入更新时执行)

在这种情况下,我只是在渲染方法之外创建了一个去抖动函数。这在使用 classes 而不是钩子时会有所不同:

挂钩:

const handleSearch = debounce(searchText => { ... }, 500);

类(或者您可以在 constructor 中对 class 字段进行去抖动,两者都有效):

class Example extends Component {
  handleSearch = debounce(searchText => { ... }, 500)

  render = () => { ... }
}

工作示例(在 codesandbox 控制台打开时键入):


去抖、节流和正常执行之间的区别:


同上,减去react-final-formreact-final-form-listeners(项目中少了两个依赖!):

工作示例(在 codesandbox 控制台打开时键入):


您的解决方案存在多个问题:

  • 使用 lodash debounce 而不是 throttle
  • 在表单外创建去抖功能,以防止在每次重新渲染或更改时重新分配它
  • 调用表单提交操作,而不是提交处理程序handleSubmit

修改并运行您的示例:

这是一个记忆化的去抖动版本:

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>}
    </>
  )}
/>