React防抖搜索:非空输入时List组件每击键重渲染的解决方法
解决React防抖搜索中List组件重复渲染的问题
问题原因
你遇到的问题核心在于:
- 每次输入按键触发
setQuery时,App组件会重新渲染 List组件未做渲染缓存,导致父组件每次重渲染时,List都会跟着重新实例化并渲染- 当前的条件渲染写法,即使
deBounceSearch没有变化,List元素也会在父组件重渲染时被重新创建
解决方案
1. 给List组件添加渲染缓存(React.memo)
React.memo会对组件的props做浅比较,只有当props变化时才会重新渲染组件。如果你的List组件没有接收props,使用memo后它只会在首次渲染或依赖变化时更新。
修改List组件的导出:
// List.tsx import React from 'react'; const List = () => { // 你的List组件逻辑 return <div>搜索结果列表</div>; }; // 用React.memo包裹组件 export default React.memo(List);
2. 优化App组件的变量声明与条件渲染
- 把
deBounceSearch的let改为const(React组件中应优先使用const声明状态或自定义hook返回值) - 统一
query的类型为string(输入框的值始终是字符串,无需设置为string | null) - 用
useMemo缓存List元素,确保只有deBounceSearch变化时才重新创建该元素
修改后的App组件:
import { useEffect, useState, useMemo } from 'react'; import useDebounce from './hooks/useDebounce'; import List from './components/List'; const App: React.FC = () => { // 统一query类型为string,初始值为空字符串 const [query, setQuery] = useState<string>(""); // 用const声明自定义hook返回值 const deBounceSearch = useDebounce(query, 2000); useEffect(() => { if (deBounceSearch) { console.log('搜索中...'); } else { console.log('等待输入...'); } }, [deBounceSearch]); // 用useMemo缓存List元素,仅当deBounceSearch变化时重新创建 const listElement = useMemo(() => { return deBounceSearch !== '' ? <List /> : null; }, [deBounceSearch]); return ( <div className="App"> <input type="text" placeholder='搜索任意内容' onChange={(e) => setQuery(e.target.value)} value={query} // 添加value绑定,确保输入框与状态同步 /> {listElement} </div> ); } export default App;
3. 优化useDebounce的类型定义
你的useDebounce实现逻辑正确,但可以替换any类型为泛型,提升类型安全性:
// useDebounce.tsx import { useState, useEffect } from 'react'; // 泛型定义,支持任意类型的防抖值 const useDebounce = <T>(value: T, delay: number): T => { const [debouncedValue, setDebouncedValue] = useState<T>(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); // 清理函数,在value变化或组件卸载时清除定时器 return () => clearTimeout(handler); }, [value, delay]); return debouncedValue; } export default useDebounce;
效果验证
完成上述修改后:
- 初始输入时,
List会在防抖延迟后渲染 - 已有关键词继续输入时,只有当防抖后的
deBounceSearch值变化时,List才会重新渲染,不会在每次按键时都重渲染
内容的提问来源于stack exchange,提问作者user2159616
相关产品推荐
相关产品推荐

