React组件读取本地JSON失败,触发Too many re-renders错误如何解决?
解决React本地JSON导入后「Too many re-renders」错误
当通过fetch请求远程URL数据源时代码可正常运行,但创建本地JSON文件并导入使用后,控制台抛出「Uncaught Error: Too many re-renders. React」错误。相关代码如下:
import React, { useState } from 'react' import { FaAngleDoubleRight } from 'react-icons/fa' import data from './data.json' function App() { const [jobs, setJobs] = useState(data) const [value, setValue] = useState(0) const newJobs = data setJobs(newJobs) const { company, dates, duties, title } = jobs[value] return ( <section className="section"> <div className="title"> <h2>experience</h2> <div className="underline"></div> </div> <div className="jobs-center"> {/* btn container */} <div className="btn-container"> {jobs.map((item, index) => { return ( <button key={item.id} onClick={() => setValue(index)} className={`job-btn ${index === value && 'active-btn'}`} > {item.company} </button> ) })} </div> {/* job info */} <article className="job-info"> <h3>{title}</h3> <h4>{company}</h4> <p className="job-date">{dates}</p> {duties.map((duty, index) => { return ( <div key={index} className="job-desc"> <FaAngleDoubleRight className="job-icon"></FaAngleDoubleRight> <p>{duty}</p> </div> ) })} </article> </div> <button type="button" className="btn"> more info </button> </section> ) } export default App;
问题原因
错误核心是在组件函数体中直接调用了setJobs(newJobs):
- 组件每次渲染时都会执行这段代码,调用
setJobs会触发组件重新渲染 - 重新渲染后又会再次执行
setJobs,形成无限循环,最终触发「Too many re-renders」错误
之前用fetch时没问题,是因为setJobs是在fetch的异步回调中执行的,只会在请求完成后触发一次状态更新;而本地JSON是同步导入的,直接在组件函数体中调用setJobs会打破渲染周期平衡。
解决方案
不需要针对本地文件场景做特殊修改,只需移除多余的状态更新代码即可。因为初始化jobs状态时已经通过useState(data)把本地JSON数据赋值给了状态,无需额外调用setJobs。
修改后的完整代码:
import React, { useState } from 'react' import { FaAngleDoubleRight } from 'react-icons/fa' import data from './data.json' function App() { const [jobs, setJobs] = useState(data) const [value, setValue] = useState(0) const { company, dates, duties, title } = jobs[value] return ( <section className="section"> <div className="title"> <h2>experience</h2> <div className="underline"></div> </div> <div className="jobs-center"> {/* btn container */} <div className="btn-container"> {jobs.map((item, index) => { return ( <button key={item.id} onClick={() => setValue(index)} className={`job-btn ${index === value && 'active-btn'}`} > {item.company} </button> ) })} </div> {/* job info */} <article className="job-info"> <h3>{title}</h3> <h4>{company}</h4> <p className="job-date">{dates}</p> {duties.map((duty, index) => { return ( <div key={index} className="job-desc"> <FaAngleDoubleRight className="job-icon"></FaAngleDoubleRight> <p>{duty}</p> </div> ) })} </article> </div> <button type="button" className="btn"> more info </button> </section> ) } export default App;
内容的提问来源于stack exchange,提问作者Alex Amiriyan
相关产品推荐
相关产品推荐

