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

React useDebounce输入防抖失效 接口频繁触发问题排查

问题描述

使用名为Combobox的输入组件时,输入字符串过程中会持续触发查询请求。已编写自定义防抖hook,预期实现输入停止500ms后再执行查询的效果,但实际功能未生效,输入时仍会持续发请求。

自定义防抖Hook代码

import { useEffect, useState } from 'react'

function useDebounce<T>(value: T, delay?: number): T {
    const [debouncedValue, setDebouncedValue] = useState<T>(value)

    useEffect(() => {
        const timer = setTimeout(() => setDebouncedValue(value), delay || 500)

        return () => {
            clearTimeout(timer)
        }
    }, [value, delay])

    return debouncedValue
}

export default useDebounce

注:上述防抖Hook实现逻辑本身没有问题

业务组件原始代码

export default function TagSelectionInput() {
    const [query, setQuery] = useState('');
    const debouncedValue = useDebounce(query, 500);
    const [filterTags, { data, loading, error }] = useLazyQuery<FilterTagsQuery>(
        filterQuery,
        {
            variables: {
                filter: query,
                offset: 0,
                limit: 20,
            },
        },
    );

    useEffect(() => {
        const fetchTags = async () => {
            if (query.length > 0) {
                const data = await filterTags();
                console.log(data);
            }
        };

        fetchTags();
    }, [data, debouncedValue, filterTags]);

    return (
        <Combobox value={query} onChange={setQuery}>
            <div className="relative">
                <SearchIcon
                    className="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-gray-400"
                    aria-hidden="true"
                />
                <Combobox.Input
                    className="border border-gray-300 rounded-md shadow-sm h-10 w-full focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm pl-11 pr-4 text-gray-800 placeholder-gray-400"
                    placeholder="Search..."
                    onChange={(event) => setQuery(event.target.value)}
                />
            </div>
            {/* 其余组件内容 */}
        </Combobox>
    )
}
问题根因

防抖失效、请求重复触发的问题全部出在业务组件的逻辑编写上,共有4处错误:

  • useEffect依赖项配置错误:将data加入了依赖数组,每次查询返回新数据后,会触发effect重新执行,形成额外的重复请求。
  • 逻辑判断未使用防抖值:触发请求的长度判断用的是实时更新的原始query值,而非防抖后的debouncedValue,输入过程中只要原始输入长度大于0就会进入请求逻辑。
  • 请求参数未使用防抖值:初始化useLazyQuery时绑定的variables取的是实时query,且调用filterTags时未动态传参,就算触发时机正确,请求携带的也是实时输入内容,达不到防抖效果。
  • 冗余依赖项:filterTags是useLazyQuery返回的稳定方法引用,不需要加入依赖数组,多余的依赖可能引发不必要的effect执行。
修复方案

调整业务组件的请求逻辑,所有触发判断、请求参数统一使用防抖后的值,修正useEffect依赖项:

export default function TagSelectionInput() {
    const [query, setQuery] = useState('');
    const debouncedValue = useDebounce(query, 500);
    // 移除初始化时写死的variables配置
    const [filterTags, { data, loading, error }] = useLazyQuery<FilterTagsQuery>(
        filterQuery
    );

    useEffect(() => {
        const fetchTags = async () => {
            // 用防抖后的值做长度判断
            if (debouncedValue.length > 0) {
                // 调用请求方法时动态传入防抖后的参数
                const res = await filterTags({
                    variables: {
                        filter: debouncedValue,
                        offset: 0,
                        limit: 20,
                    }
                });
                console.log(res);
            }
        };

        fetchTags();
        // 只保留防抖值作为唯一依赖,移除data、filterTags等冗余/错误依赖
    }, [debouncedValue]);

    return (
        <Combobox value={query} onChange={setQuery}>
            <div className="relative">
                <SearchIcon
                    className="pointer-events-none absolute top-3.5 left-4 h-5 w-5 text-gray-400"
                    aria-hidden="true"
                />
                <Combobox.Input
                    className="border border-gray-300 rounded-md shadow-sm h-10 w-full focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm pl-11 pr-4 text-gray-800 placeholder-gray-400"
                    placeholder="Search..."
                    onChange={(event) => setQuery(event.target.value)}
                />
            </div>
            {/* 其余原有组件内容 */}
        </Combobox>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 08:21:25