Next.js过多重渲染错误求助:动态菜单实现遇阻
解决Next.js动态菜单生成的无限重渲染问题
问题背景
需要基于固定JSON数据生成「主菜单包含子菜单」的动态菜单结构,无法修改JSON文件,开发时遇到Too many re-renders. React limits the number of renders to prevent an infinite loop错误。
错误原因
- 组件顶层直接执行状态更新:在组件函数顶层遍历数据并调用
setMenu、setSubMenu,每次状态更新会触发组件重新渲染,重新渲染后又会重复执行状态更新操作,形成无限循环。 - 错误的组件类型声明:将使用
useState、useEffect的Client Component标记为async,但这类组件不能是异步函数。 - 数据获取错误:接口返回的JSON中
menus是根对象下的数组,原代码直接将整个返回对象赋值给状态,导致后续遍历逻辑出错。 - 冗余状态变量:用
subMenu状态临时存储子菜单,多次调用setSubMenu会额外触发渲染,且子菜单可直接通过计算得到,无需单独维护状态。
修复后的代码
import { useEffect, useState } from "react"; export default function MenuCreator() { const [menu, setMenu] = useState([]); const [menuData, setMenuData] = useState([]); useEffect(() => { fetch("http://localhost:8000/menus") .then((res) => { if (!res.ok) throw Error("请求菜单数据失败"); return res.json(); }) .then((data) => { // 从返回的JSON中提取menus数组 setMenuData(data.menus); }) .catch(err => console.error(err)); }, []); // 当原始菜单数据更新时,生成带层级的菜单结构 useEffect(() => { if (menuData.length === 0) return; // 筛选所有主菜单(main_menu为null的项) const mainMenus = menuData.filter(item => item.main_menu === null); // 为主菜单匹配对应的子菜单 const structuredMenu = mainMenus.map(main => ({ ...main, subMenus: menuData.filter(sub => sub.main_menu === main.id) })); setMenu(structuredMenu); }, [menuData]); return { menu }; }
关键修复说明
- 数据处理逻辑移入useEffect:依赖
menuData状态,确保仅在原始菜单数据加载完成后执行一次结构转换,避免重复触发状态更新。 - 移除异步组件声明:Client Component不能是
async函数,改为普通函数。 - 修正数据提取逻辑:正确从返回的JSON对象中取出
menus数组。 - 简化状态管理:不再使用临时
subMenu状态,直接通过数组方法计算主菜单对应的子菜单,一次性更新menu状态,减少不必要的渲染触发。
内容的提问来源于stack exchange,提问作者Samet ÖZTÜRK
相关产品推荐
相关产品推荐

