React使用useState对象时,如何避免相同值setState引发的初始重渲染?
减少React组件无用重渲染的问题处理
我明确知道自己漏了些关键点,但没找到清晰答案。现在想减少组件重渲染次数,尤其要避免这种无用渲染场景:
- 状态用对象类型,想通过单次
setState同时设置loading和products属性; - 初始
loading设为true,因为useEffect至少会执行一次; useEffect里调用setState会触发一次无意义的即时重渲染,这和React对对象的浅比较机制有关。
实际代码
export const ProductsIndex = () => { console.log('[ProductsIndex] Rendering'); const [state, setState] = useState({ loading: true, products: [], pages: 1 }); useEffect(() => { console.log('[ProductsIndex] useEffect'); setState(prev => ({ ...prev, loading: true })); axios.get('/api/products', params) .then(res => { setState(prev => ({ ...prev, loading: false, products: res.data })); }); // fetch }, [params]); };
我想到的解决方案
useEffect(() => { console.log('[ProductsIndex] useEffect'); setState(prev => prev.loading ? prev : { ...prev, loading: true }); }, []);
更优处理方式
1. 去掉冗余的初始loading设置
初始状态里loading已经是true,第一次进入useEffect时完全没必要再调用setState设置loading——新创建的对象引用和原状态不同,React浅比较后会判定状态变化,触发无意义重渲染。直接发起请求即可:
useEffect(() => { console.log('[ProductsIndex] useEffect'); axios.get('/api/products', params) .then(res => { setState(prev => ({ ...prev, loading: false, products: res.data })); }); }, [params]);
2. 拆分独立状态(推荐优化)
如果状态中各属性更新频率不同,把它们拆成独立的useState,能彻底避免对象浅比较带来的不必要重渲染,逻辑也更清晰:
export const ProductsIndex = () => { console.log('[ProductsIndex] Rendering'); const [loading, setLoading] = useState(true); const [products, setProducts] = useState([]); const [pages, setPages] = useState(1); useEffect(() => { console.log('[ProductsIndex] useEffect'); // 仅当loading不是true时才更新,避免无用渲染 if (!loading) setLoading(true); axios.get('/api/products', params) .then(res => { setLoading(false); setProducts(res.data); }); }, [params, loading]); };
3. 优化你的原有方案
如果坚持保留对象状态,记得把params加入依赖数组(否则参数变化时不会重新请求),同时简化判断逻辑:
useEffect(() => { console.log('[ProductsIndex] useEffect'); setState(prev => prev.loading ? prev : { ...prev, loading: true }); axios.get('/api/products', params) .then(res => { setState(prev => ({ ...prev, loading: false, products: res.data })); }); }, [params]);
内容的提问来源于stack exchange,提问作者gremo
相关产品推荐
相关产品推荐

