React项目实现debounce防抖功能不生效,请问问题出在哪里?
问题原因
- 防抖函数调用逻辑错误:当前
newHandleTextChange的写法是每次触发onChange事件时,立即执行handleTextChange(val),再把执行结果传给debounce,相当于要防抖的逻辑当场就运行了,没有延迟效果。同时每次触发事件都会生成一个全新的防抖函数实例,内部的timer变量无法复用,前一次的定时器根本没法清除。 - 防抖函数定义位置错误:把
debounce定义在组件内部,组件每次状态更新重渲染时,都会重新生成新的debounce函数,之前保存的定时器ID会直接丢失,防抖逻辑自然无法生效。 - 参数传递错误:
debounce的第一个参数要求传入函数本身,你现在传的是handleTextChange(val)的执行返回值(setText的返回值是undefined),完全不符合防抖函数的入参要求。
修复方案
调整逻辑如下:
- 将debounce函数移到组件外部,避免重渲染被重置
- 用
useCallback包裹防抖后的输入处理函数,保证函数引用稳定,timer可复用 - 正确传递函数给debounce,不要提前执行
修复后完整代码:
import React, { useEffect, useState, useMemo, useCallback } from 'react'; import axios from 'axios'; const API = 'https://jsonplaceholder.typicode.com/posts'; // 防抖函数挪到组件外部,全局唯一 const debounce = (fn, delay) => { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, args); }, delay); } } const AutoComplete2 = () => { const [text, setText] = useState("") const [posts, setPosts] = useState([]) useEffect(() => { async function fetchData() { const data = await axios.get(API); if(parseInt(data.status) !== 200) return; setPosts(data.data) } fetchData(); }, []) const handleTextChange = (event) => setText(event.target.value); // 提前生成防抖后的处理函数,用useCallback保证引用不随渲染变化 const debouncedHandleChange = useCallback(debounce(handleTextChange, 5000), []) const handleSelectOption = (str) => setText(str); const showOptions = useMemo(() => { if(text === '') return; const showPosts = [...posts].filter((ele) => ele.title.toLowerCase().includes(text.toLowerCase())); if(showPosts.length === 1) { setText(showPosts[0].title); } else { return ( <div> {showPosts.map((obj, index) => { return ( <div key={index} > <span onClick={() => handleSelectOption(obj.title)} style={{cursor: 'pointer'}}> {obj.title} </span> </div> ) })} </div> ) } }, [text, posts]) return ( <div> {/* 直接绑定防抖后的函数 */} <input type="text" value={text} onChange={debouncedHandleChange} /> {showOptions} </div> ) } export default AutoComplete2;
内容的提问来源于stack exchange,提问作者myTest532 myTest532
相关产品推荐
相关产品推荐

