Используя debounce для поиска в реакции

У меня есть вход для поиска, чтобы сделать вызовы API на лету. Я хотел бы реализовать debounce, чтобы уменьшить количество обращений к серверу.

  _debouncedSearch() {
    debounce(this.props.fetchRoutes(this.state.searchText), 1000);
  }

  _updateResults(searchText) {
    this.setState({searchText});
    this._debouncedSearch();
  }

Я ожидаю debouncedSearch каждую 1 секунду Но это все еще называется на лету. И скинуть ошибки:

Uncaught TypeError: Ожидается функция при отладке (lodash.js? 3387: 10334)

Uncaught Error: возникла перекрестная ошибка. У React нет доступа к фактическому объекту ошибки в разработке.

Я чувствую, что этот вопрос нужно задавать часто, но мне кажется, что ни одно из решений не работает. Может ли кто-нибудь объяснить мне, в чем именно проблема? Я думал, что debounce - это просто setTimeOut.

Спасибо

3 ответа

Решение

_.debounce уже выполненная функция (функция возвращает функцию) . затем _debouncedSearch должен быть атрибутом класса, а не методом:

  _debouncedSearch=  debounce(() => this.props.fetchRoutes(this.state.searchText), 1000);

вместо:

  _debouncedSearch() {
    debounce(this.props.fetchRoutes(this.state.searchText), 1000);
  }

Кроме того, обратите внимание, первый аргумент _.debounce это функция (() => this.props.fetchRoutes...), а не напрямую this.props.fetchRoutes...

constructor(props) {
    super(props);
    this.state = {
      searchText: '',
    };
    this._debouncedSearch = debounce(
      () => this.props.fetchRoutes(this.state.searchText),
      1000
    );
  }

  _updateResults(searchText) {
    this.setState({searchText});
    this._debouncedSearch();
  }

Вот полный рабочий код на случай, если кому-то это нужно!

Недавно нашел этот вопрос полезным. Вот мое оптимизированное решение:

      const [searchTerm, setSearchTerm] = useState("");
const [result, setResult] = useState([]);

async function fetchData(searchTerm: string) {
  const { data } = await client.query(searchTerm);
  setResult(data);
}

const debounceLoadData = useMemo(() => debounce(fetchData, 700), []);

useEffect(() => {
  window.addEventListener("keydown", debounceLoadData(searchTerm));
  return () => {
    window.removeEventListener("keydown", debounceLoadData(searchTerm));
  };
}, [searchTerm]);

Это вызовет функцию только один раз после того, как пользователь перестанет печатать в течение 700 мс. Затем я использую useMemoкэшировать каждый результат. Если пользователь ищет одно и то же значение несколько раз, он вернет кэшированное значение и не вызовет fetchData()функционировать больше, чем необходимо.

Другие вопросы по тегам