【问题标题】:how to debounce a final-form Field?如何去抖动最终形式的字段?
【发布时间】:2019-12-11 06:02:09
【问题描述】:

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

我的需求很简单,我想在用户写一些文本时分派搜索,但我想在字段中添加一个throttle

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

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

【问题讨论】:

    标签: 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-formreact-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>}
            </>
          )}
        />
        

        【讨论】:

          猜你喜欢
          • 2021-11-21
          • 1970-01-01
          • 1970-01-01
          • 2018-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多