You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

封装AntD Select防抖搜索组件时遇到功能异常问题

AntD Select防抖搜索后续输入异常的解决方法

问题根因

你遇到的是典型的闭包陷阱:防抖函数通过useMemo创建时依赖项为空,导致它始终引用组件首次渲染时的上下文。连续输入时,防抖函数内部无法获取到最新的输入值或state,自然没法正确更新searchValue。

两种可行解决办法

方法一:让防抖函数直接接收输入值

不让防抖函数依赖组件内部state,直接把输入值作为参数传入,同时用useCallback包裹防抖函数(保证稳定的同时避免重复创建):

import React, { useState, useCallback } from 'react';
import { Select } from 'antd';
import debounce from 'lodash/debounce';

const CustomSelect = () => {
  const [searchValue, setSearchValue] = useState('');
  
  // 用useCallback包裹,确保防抖函数能稳定获取setSearchValue
  const debouncedSearch = useCallback(
    debounce((inputValue) => {
      setSearchValue(inputValue);
    }, 500),
    [] // setSearchValue是React稳定提供的,无需加进依赖
  );

  const handleSearch = (value) => {
    debouncedSearch(value);
  };

  return (
    <Select
      showSearch
      style={{ width: 200 }}
      onSearch={handleSearch}
      placeholder="请搜索"
    />
  );
};

export default CustomSelect;

方法二:用useRef存最新输入值

如果防抖逻辑需要基于当前state做处理,用useRef保存最新的输入值,就能绕过闭包拿不到最新值的问题:

import React, { useState, useRef, useCallback } from 'react';
import { Select } from 'antd';
import debounce from 'lodash/debounce';

const CustomSelect = () => {
  const [searchValue, setSearchValue] = useState('');
  // 用ref存最新的输入值,不受闭包影响
  const latestInput = useRef('');
  
  const debouncedSearch = useCallback(
    debounce(() => {
      setSearchValue(latestInput.current);
    }, 500),
    []
  );

  const handleSearch = (value) => {
    latestInput.current = value;
    debouncedSearch();
  };

  return (
    <Select
      showSearch
      style={{ width: 200 }}
      onSearch={handleSearch}
      placeholder="请搜索"
    />
  );
};

export default CustomSelect;

核心注意点

  • 尽量不要在防抖函数里直接用组件的state,要么传参数,要么用useRef存最新值,避开闭包陷阱。
  • 用useCallback或useMemo包裹防抖函数时,依赖项只加必要的,避免频繁重建防抖函数浪费性能。

内容的提问来源于stack exchange,提问作者pnetm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:40:55