如何正确使用debox with redux-form?

时间:2017-10-29 07:05:32

标签: javascript reactjs redux lodash

我有搜索输入。

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

我在Stack Overflow上添加了基于this answer的lodash debounce

const { searchMails } = this.props;

const debounceSearchMails = debounce(searchMails, 1000);
debounceSearchMails(keyword);

行动

export const searchMails = keyword => ({ type: SEARCH_MAILS, payload: keyword });

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

h
he
hel
hell
hello

如何正确使用去抖?感谢

更新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);

更新2

我将行动改为

const searchMails0 = keyword => ({ type: SEARCH_MAILS, payload: keyword });
export const searchMails = debounce(searchMails0, 1000);

但仍然相同。

更新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>
    );
  }
}

UDPATE 4:

我发现问题与setTimeout有某种关联,如果我有以下情况,debounce将无效。如果我删除setTimeoutdebounce将有效。但是onChange将始终返回最后一个值。所以我确实需要它,因为redux-form的this "issue"

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

1 个答案:

答案 0 :(得分:5)

首先非常感谢@zerkms。如果没有正确方向的指导,我就无法做到。

  

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

检查onChange's type后,这是最终的工作代码:

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

经验教训:

  • 我从未想过我可以在构造函数中执行this.debouncedSubmit = debounce(this.onSubmit, 1000);之类的操作。

  • 我一直认为我必须使用redux-form中的handleSubmit,但事实证明并非适用于所有情况。

  • 需要深入。