React衍生状态问题:这段代码存在哪些问题?
React代码未用useMemo/useRef的深层问题解析(针对你的场景)
一、未用useMemo处理过滤逻辑的核心问题
- 无意义的重复计算:只要组件触发渲染(哪怕
searchTerm没变化,比如父组件传的其他props更新、组件自身其他state变动),过滤逻辑就会重新执行一次。如果products数据量较大(比如几百上千条),这会额外消耗CPU资源,在移动端低配置设备或性能敏感场景下,可能导致页面响应变慢。 - 触发子组件不必要重渲染:如果过滤后的
filteredProducts作为props传给子组件,没加useMemo的话,每次组件渲染都会生成一个全新的数组引用(哪怕数组内容完全一致)。React的props浅比较会判定props发生变化,进而触发子组件重渲染——这是最常见的性能浪费点,而你只监测了当前组件的渲染次数,没关注子组件,所以没发现差异。
二、未用useRef存储products的潜在问题
分两种常见场景:
- products是父组件传入的props:如果父组件每次渲染都生成新的
products数组(比如用[...originalData]这种写法,哪怕内容没变化),React会判定props更新,导致当前组件无意义重渲染。用useRef存储的话,可以通过useEffect对比内容,仅当products真的变更时才更新ref,避免触发不必要的过滤逻辑。 - products是异步获取的数据:存到
useRef里可以让你在定时器、事件回调等异步场景中,始终访问到最新的products数据,而不会因为组件渲染闭包问题拿到旧值。如果是静态初始化的数据,用不用useRef影响不大。
三、为什么你测渲染次数没发现差异?
你只关注了当前组件的渲染次数,但问题核心不在这:
- 当
searchTerm变化时,不管用不用useMemo,当前组件都会因state更新触发渲染,所以次数一致。 - 真正的差异体现在渲染过程中的计算开销和子组件渲染次数:不用
useMemo时,只要组件因其他原因渲染,过滤逻辑就会重复执行;若有子组件接收过滤结果,子组件会跟着无意义重渲染。
举个真实场景的代码对比
未优化版(你的当前代码大概率类似)
function ProductList({ products }) { const [searchTerm, setSearchTerm] = useState(''); // 每次渲染都会重新执行过滤 const filteredProducts = products.filter(item => item.name.includes(searchTerm) ); return ( <div> <input onChange={(e) => setSearchTerm(e.target.value)} /> <ProductItems items={filteredProducts} /> </div> ); }
只要父组件重新渲染(哪怕products和searchTerm都没变),filteredProducts会生成新数组,导致ProductItems强制重渲染。
优化版
function ProductList({ products }) { const [searchTerm, setSearchTerm] = useState(''); const productsRef = useRef(products); // 仅当products内容真正变化时更新ref useEffect(() => { if (JSON.stringify(products) !== JSON.stringify(productsRef.current)) { productsRef.current = products; } }, [products]); // 仅当searchTerm或products变化时重新过滤 const filteredProducts = useMemo(() => { return productsRef.current.filter(item => item.name.includes(searchTerm)); }, [searchTerm, productsRef.current]); return ( <div> <input onChange={(e) => setSearchTerm(e.target.value)} /> <ProductItems items={filteredProducts} /> </div> ); }
这样只有searchTerm或products真的变化时,才会执行过滤,子组件也仅在filteredProducts内容变更时重渲染。
内容的提问来源于stack exchange,提问作者stackoverflower
相关产品推荐
相关产品推荐

