如何使用redux-form正确使用debounce?

Hon*_*iao 2 javascript lodash reactjs redux

我有一个搜索输入.

const { searchMails } = this.props;
searchMails(keyword);
Run Code Online (Sandbox Code Playgroud)

我在Stack Overflow上debounce根据这个答案添加了lodash .

const { searchMails } = this.props;

const debounceSearchMails = debounce(searchMails, 1000);
debounceSearchMails(keyword);
Run Code Online (Sandbox Code Playgroud)

那个行动

export const searchMails = keyword => ({ type: SEARCH_MAILS, payload: keyword });
Run Code Online (Sandbox Code Playgroud)

但是,添加后debounce,当我输入"hello"时,它会searchMails在1秒后触发5次.有效载荷是

h
he
hel
hell
hello
Run Code Online (Sandbox Code Playgroud)

如何正确使用去抖?谢谢

更新1:添加完整代码

import React, { PureComponent } from 'react';
import { Field, reduxForm, reset } from 'redux-form';
import { Form } from 'reactstrap';
import debounce from 'lodash/debounce';

class Search extends PureComponent {
  constructor(props) {
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
  }

  onSubmit(values) {
    const { searchMails } = this.props;

    const debounceSearchMails = debounce(searchMails, 1000);
    debounceSearchMails(values.keyword);
  }

  render() {
    const { handleSubmit, keyword } = this.props;

    return (
      <Form onSubmit={handleSubmit(this.onSubmit)}>
        <Field name="keyword" component="input" type="search" onChange={() => setTimeout(handleSubmit(this.onSubmit))} />
      </Form>
    );
  }
}

function validate(values) {
  const errors = {};
  return errors;
}

export default reduxForm({
  validate,
  form: 'searchForm'
})(Search);
Run Code Online (Sandbox Code Playgroud)

更新2:

我改变了行动

const searchMails0 = keyword => ({ type: SEARCH_MAILS, payload: keyword });
export const searchMails = debounce(searchMails0, 1000);
Run Code Online (Sandbox Code Playgroud)

但仍然相同.

更新3:这次我改为此,但仍然相同.

class Search extends PureComponent {
  constructor(props) {
    super(props);
    this.onSubmit = this.onSubmit.bind(this);
    this.debouncedSubmit = debounce(this.onSubmit, 1000);
  }

  onSubmit(values) {
    const { searchMails } = this.props;
    searchMails(values.keyword);
  }

  render() {
    const { handleSubmit, keyword } = this.props;
    return (
      <Form onSubmit={handleSubmit(this.debouncedSubmit)}>
        <Field name="keyword" component="input" type="search" onChange={() => setTimeout(handleSubmit(this.debouncedSubmit))} />
      </Form>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

UDPATE 4:

我发现这个问题与某种程度上有关setTimeout,如果我有这样的话,那就不行了debounce.如果我删除setTimeout,debounce将工作.但随后onChange将始终返回最后一个值.所以我确实需要它,因为redux-form的这个"问题"

<Field component="input" type="search" onChange={() => setTimeout(handleSubmit(debounce(this.onSubmit, 1000)))}/>
Run Code Online (Sandbox Code Playgroud)

Hon*_*iao 5

首先非常感谢@zerkms.没有他正确方向的指导,我无法做到.

您应该只创建一次debounced函数然后再使用它.它是去抖动功能,内部保持去抖所需的状态.目前,您在每次击键时重新创建它. - zerkms

在检查了更改类型之后,这是最终的工作代码:

class Search extends PureComponent {
  constructor(props) {
    super(props);

    this.onSubmit = this.onSubmit.bind(this);
    this.onChange = this.onChange.bind(this);
    this.debouncedOnChange = debounce(this.onChange, 1000);
  }

  onSubmit(values) {
    const { searchMails } = this.props;
    searchMails(values.keyword);
  }

  onChange(event, newValue, previousValue) {
    const { searchMails } = this.props;
    searchMails(newValue);  // the second parameter is new value
  }

  render() {
    const { keyword } = this.props;
    return (
      <Form onSubmit={handleSubmit(this.onSubmit)}>
        <Field component="input" type="search" onChange={this.debouncedOnChange}/>
      </Form>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

得到教训:

  • 我从没想过我能this.debouncedSubmit = debounce(this.onSubmit, 1000);在构造函数中做些什么.

  • 我一直认为我必须使用handleSubmitredux-form,但事实证明并非适用于所有情况.

  • 需要深入了解.