React组件遍历对象数组调用setState触发无限循环如何解决?
问题原因
- 状态更新逻辑没有放在生命周期钩子中,直接在组件渲染流程执行。每次调用
setName会触发组件重新渲染,新的渲染流程又会再次执行数据处理逻辑、调用setName,形成无限循环。 - 在
forEach循环中重复调用setName,由于React状态更新是批量异步的,循环过程中获取到的name始终是初始值,无法得到拼接完成的姓名数组。 forEach是同步方法,前面添加await属于无效写法,没有实际作用。
解决方案
核心修改逻辑
- 使用
useEffect钩子包裹数据处理逻辑,指定依赖项为prop传入的testInfo,保证只有testInfo发生变化时才会重新处理数据,避免循环触发渲染。 - 不要在循环中重复调用
setState,直接使用数组map方法一次性提取所有需要的字段后再更新状态,减少不必要的性能开销。
修改后的Gallary组件代码
import {useState, useEffect} from 'react'; const Gallary = ( {testInfo, title, profImg, posterName, imgUrl, dlL} ) => { // 重命名状态避免和单条姓名变量混淆 const [nameList, setNameList] = useState([]); useEffect(() => { // 一次性提取所有姓名后更新状态 const names = testInfo.map(item => item.name); setNameList(names); }, [testInfo]) return ( <div className="gallary-section"> <h2>{ title }</h2> <div className="gallary"> <GalImg profileImg={profImg} name={nameList.length > 0 ? nameList : [posterName]} picUrl={imgUrl} dlLink={dlL} /> </div> <Button bgColor="#7E4DD2" txtColor="#fff" btnText="More" /> </div> ) } Gallary.defaultProps = { title: "Today's selection", profImg: "https://images.pexels.com/users/avatars/92810756/brian-lazo-240.jpeg?auto=compress&fit=crop&h=256&w=256", posterName: "Brian Lazo", imgUrl: "https://images.pexels.com/photos/9160984/pexels-photo-9160984.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260", dlL: "https://www.pexels.com/photo/9160984/download/?search_query=&tracking_id=so1xqtw586" }
额外优化建议
如果仅需要从testInfo中提取姓名用于渲染,不需要单独维护一个state存储姓名列表,直接在渲染阶段使用testInfo.map(item => item.name)即可,可省略冗余的状态管理逻辑,进一步降低性能开销。
另外原代码中name > 0的判断逻辑错误,数组是否存在有效值需要通过数组.length属性判断,不能直接用数组和数值做比较。
内容的提问来源于stack exchange,提问作者Ruination
相关产品推荐
相关产品推荐

