如何在 React 中实现一个防抖(debounce)的搜索输入框?

如何在 React 中实现一个防抖(debounce)的搜索输入框?

回答与解析:

在 React 中实现防抖搜索输入框,核心是使用防抖函数来限制搜索请求的频率,避免用户每输入一个字符就触发一次 API 请求。可以通过自定义 Hook 或直接在组件中使用 useCallbackuseEffect 结合防抖逻辑实现。

示例代码如下:

import { useState, useEffect, useCallback } from 'react';

// 防抖函数
function debounce(func, delay) {
  let timeoutId;
  return function (...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

function SearchInput() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  // 模拟搜索 API
  const performSearch = async (searchTerm) => {
    if (searchTerm.trim() === '') {
      setResults([]);
      return;
    }
    // 假设调用 API
    const mockResults = [`Result for "${searchTerm}" 1`, `Result for "${searchTerm}" 2`];
    setResults(mockResults);
  };

  // 使用 useCallback 缓存防抖函数,避免每次渲染都重新创建
  const debouncedSearch = useCallback(
    debounce((q) => performSearch(q), 500),
    []
  );

  useEffect(() => {
    debouncedSearch(query);
    // 清理函数可选(防抖本身已通过 clearTimeout 控制)
    return () => {
      // 可在此处清除最后一个 timeout(非必需)
    };
  }, [query, debouncedSearch]);

  return (
    <div>
      <input
        type="text"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      <ul>
        {results.map((result, index) => (
          <li key={index}>{result}</li>
        ))}
      </ul>
    </div>
  );
}

export default SearchInput;

关键点解析:

  1. 防抖原理:通过 setTimeout 延迟执行函数,若在延迟期间再次触发,则清除之前的定时器并重新计时。
  2. useCallback:防止 debouncedSearch 在每次渲染时重新创建,否则 useEffect 会因依赖变化而频繁执行。
  3. 副作用管理:在 useEffect 中调用防抖函数,确保 query 变化后触发搜索逻辑。
  4. 性能优化:避免高频输入导致大量无效请求,提升用户体验和服务器负载。

注意:若使用第三方库(如 lodash),可直接用 _.debounce,但需注意在组件卸载时取消 pending 的调用,防止内存泄漏。

发表评论 (审核通过后显示评论):

昵称:
邮箱:
内容: