如何解决React中useMemo内map引发的无限循环问题
解决React状态更新引发的无限循环问题
问题根源
你的代码触发无限循环有两个核心原因:
test是组件内部直接定义的数组,每次组件重渲染都会创建新的数组引用,导致useMemo的依赖项每次都变化,useMemo回调反复执行。useMemo的设计目的是缓存计算结果,你却在其中直接调用状态更新函数,状态变更触发组件重渲染,进一步加剧循环。
修复方案
1. 稳定依赖项的引用
把test改为组件外部常量,或用useMemo包裹确保引用不变:
// 方式1:移到组件外部 const test = [{ "myId": "", "myLabel": "" }]; // 方式2:组件内部用useMemo缓存 const test = useMemo(() => [{ "myId": "", "myLabel": "" }], []);
2. 用useEffect处理状态更新副作用
将状态更新逻辑移到useEffect中(副作用专属钩子),避免在useMemo里执行状态变更:
const [budgetYear, setBudgetYear] = useState(0); const [budgetMonth, setBudgetMonth] = useState(0); const [budgetCustomers, setBudgetCustomers] = useState([] as string[]); // 稳定test的引用 const test = useMemo(() => [{ "myId": "", "myLabel": "" }], []); useEffect(() => { // 处理data的添加逻辑(如果data是组件状态,要用状态更新函数,禁止直接push) // 示例:setData(prev => [...prev, ['value1', 'value2', 'value3']]); // 遍历dateCols更新状态 dateCols.forEach((date) => { const [yearStr, monthStr] = date.name.split("-"); const year = Number(yearStr); const month = Number(monthStr); // 注意:遍历多个date项时,最后一次更新会覆盖之前的状态 // 如果需要保存所有年份/月份,需将状态改为数组类型 setBudgetYear(year); setBudgetMonth(month - 1); setBudgetCustomers(['123','234','345','456']); }); }, [test, dateCols]);
3. 优化多项状态更新逻辑
如果dateCols包含多个项,多次调用状态更新会导致最终仅保留最后一次结果。若需保存所有数据,应将状态改为数组:
// 定义数组类型的状态 const [budgetItems, setBudgetItems] = useState<{year: number, month: number, customers: string[]}[]>([]); useEffect(() => { const newBudgetItems = dateCols.map(date => { const [yearStr, monthStr] = date.name.split("-"); return { year: Number(yearStr), month: Number(monthStr) - 1, customers: ['123','234','345','456'] }; }); setBudgetItems(newBudgetItems); }, [test, dateCols]);
4. 确保dateCols引用稳定
如果dateCols是父组件传递的props或派生数据,同样要用useMemo包裹,避免因引用频繁变化导致useEffect重复执行。
内容的提问来源于stack exchange,提问作者user1601716
相关产品推荐
相关产品推荐

