React 18.2.0递归生成嵌套JSON表单遇无限重渲染问题求助
解决递归渲染嵌套JSON导致的"Too many re-renders"错误
问题原因
你当前代码的核心问题是在组件渲染周期中直接调用setDisplayForm:每次组件渲染时,都会执行setDisplayForm(builtForm)触发state更新;state更新又会触发组件重新渲染,如此循环往复,直接导致无限重渲染错误。另外,将JSX元素存储到state里也不符合React的最佳实践,React更推荐直接在渲染逻辑中生成UI。
解决方案
- 移除不必要的state:不需要把渲染结果存入state,直接在组件的return逻辑中调用递归函数生成UI。
- 优化递归判断逻辑:替换
JSON.stringify的低效判断方式,直接通过类型检查和属性存在性判断来决定是否递归,提升性能。 - 用
useMemo缓存渲染结果:针对深度嵌套的JSON,用useMemo缓存递归生成的JSX,避免每次渲染都重复执行递归逻辑。
修改后的代码
import { useState, useMemo } from 'react'; import reactLogo from './assets/react.svg'; import viteLogo from '/vite.svg'; import './App.css'; function App() { // 示例深度嵌套JSON,替换为你的实际数据 const input = { label: "表单", properties: { name: { label: "姓名", type: "text" }, contact: { label: "联系方式", properties: { phone: { label: "手机号", type: "tel" }, email: { label: "邮箱", type: "email" } } } } }; const displayProperties = useMemo(() => { const renderProperties = (properties) => { return ( <> {Object.entries(properties).map(([key, value]) => { // 跳过非对象类型的非label属性,可根据需求调整 if (key !== 'label' && typeof value !== 'object') return null; return ( <div key={`${key}-${JSON.stringify(value)}`}> {key === 'label' && <span>{value}</span>} {typeof value === 'object' && value !== null && ( (value.properties || value.label) && renderProperties(value) )} {/* 根据type渲染对应输入字段 */} {key === 'type' && <input type={value} placeholder="请输入内容" />} </div> ); })} </> ); }; return renderProperties(input); }, [input]); return <>{displayProperties}</>; } export default App;
关键优化点说明
- 移除
setDisplayForm和对应state:直接在useMemo中生成并缓存渲染结果,避免state更新触发的循环。 - 高效递归判断:用
typeof value === 'object' && value !== null判断对象类型,再检查是否包含properties或label属性,比JSON.stringify性能更优。 - 合理的key值:用
${key}-${JSON.stringify(value)}作为map的key,避免使用index导致的渲染异常。 - 输入字段渲染逻辑:根据
type属性渲染对应类型的输入框,匹配你"根据值渲染对应输入字段"的需求。
内容的提问来源于stack exchange,提问作者Common Man
相关产品推荐
相关产品推荐

