React Redux中实现Input的handleChange防抖处理求助
解决React表单Input的handleChange防抖问题
直接在组件中使用防抖函数容易因为组件重新渲染导致防抖失效,核心原因是每次渲染都会创建新的防抖函数实例。下面提供两种可行的实现方案:
方案一:使用lodash的debounce
import { debounce } from 'lodash'; import { useDispatch, useCallback, useRef, useEffect } from 'react'; const FormIntestazione = (props) => { const dispatch = useDispatch(); const intestazione = props.intestazione; // 用useRef持久化防抖函数实例,避免重复创建 const debouncedDispatchRef = useRef(); // 初始化防抖函数 if (!debouncedDispatchRef.current) { debouncedDispatchRef.current = debounce((id, value) => { dispatch(actionSetContratto(id, value)); }, 500); // 防抖延迟,可根据需求调整 } // 用useCallback保证handleChange引用稳定 const handleChange = useCallback((event) => { const { id, value } = event.target; debouncedDispatchRef.current(id, value); }, []); // 组件卸载时清除定时器,避免内存泄漏 useEffect(() => { return () => { debouncedDispatchRef.current?.cancel(); }; }, []); return ( <Box id="intestazione" component="form" sx={{ '& .MuiTextField-root': { m: 1, width: '25ch' }, }} noValidate autoComplete="off" > <div> <div> <TextField label="Numero Riferimento" value={intestazione.Riferimento} onChange={handleChange} id="Riferimento" size="small" /> </div> </div> </Box> ); };
方案二:自定义防抖函数
如果不想引入lodash,可以自己实现防抖逻辑:
import { useDispatch, useCallback, useRef, useEffect } from 'react'; // 自定义带cancel方法的防抖函数 const debounce = (func, delay) => { let timeoutId; const debouncedFunc = (...args) => { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; debouncedFunc.cancel = () => clearTimeout(timeoutId); return debouncedFunc; }; const FormIntestazione = (props) => { const dispatch = useDispatch(); const intestazione = props.intestazione; const debouncedDispatchRef = useRef(); if (!debouncedDispatchRef.current) { debouncedDispatchRef.current = debounce((id, value) => { dispatch(actionSetContratto(id, value)); }, 500); } const handleChange = useCallback((event) => { const { id, value } = event.target; debouncedDispatchRef.current(id, value); }, []); useEffect(() => { return () => { debouncedDispatchRef.current?.cancel(); }; }, []); return ( <Box id="intestazione" component="form" sx={{ '& .MuiTextField-root': { m: 1, width: '25ch' }, }} noValidate autoComplete="off" > <div> <div> <TextField label="Numero Riferimento" value={intestazione.Riferimento} onChange={handleChange} id="Riferimento" size="small" /> </div> </div> </Box> ); };
关键注意点
useRef用于保存防抖函数实例,确保组件每次渲染都复用同一个函数,避免防抖失效useCallback包裹handleChange,保证其引用稳定,防止TextField频繁重新渲染- 组件卸载时调用
cancel方法清除定时器,避免内存泄漏 - 防抖延迟时间可根据业务需求调整(比如300ms/500ms)
内容的提问来源于stack exchange,提问作者Roberto Empiri
相关产品推荐
相关产品推荐

