React调用setState出现Too many re-renders重渲染错误如何解决
报错根因
- 两种写法触发死循环的核心原因是 状态更新逻辑直接放在了组件顶层作用域:
- React组件每次渲染都会执行顶层的所有代码,你调用
setRatingFinal会触发组件重新渲染,重新渲染又会再次执行setRatingFinal,形成无限循环,最终触发Too many re-renders报错 - 遍历过程中直接调用
setRatingFinal的写法问题更严重,单次渲染就会触发3021次状态更新,性能和渲染逻辑都会直接崩溃
- React组件每次渲染都会执行顶层的所有代码,你调用
正确实现方案
有两种常用的实现方式,可根据你的业务场景选择:
- 用useEffect封装计算逻辑:仅在依赖项(这里是movies数组)变化时才重新计算并更新状态,适合后续需要修改
ratingFinal的场景 - 用useMemo缓存计算结果:不需要单独声明状态,直接缓存计算后的数组,适合
ratingFinal只用于渲染、不需要后续修改的场景,代码更简洁
可运行代码示例
方案1:useEffect实现(支持后续修改ratingFinal)
import { useState, useEffect } from 'react'; // 示例movies数组,可替换为实际数据源 const movies = Array.from({length: 3021}, () => ({ "IMDB Rating": +(Math.random() * 10).toFixed(1), "IMDB Votes": Math.floor(Math.random() * 10000) })) function MovieRatingList() { const [ratingFinal, setRatingFinal] = useState([]); useEffect(() => { // 计算逻辑全部放到useEffect内部,仅在依赖项变化时执行 const processedList = movies.map(item => { return { ...item, // 计算 votes * rating 的结果 "RatingTotal": item["IMDB Rating"] * item["IMDB Votes"] } }) setRatingFinal(processedList); }, [movies]) // 依赖项填movies,仅当movies变化时重新计算 // 渲染逻辑 return ( <div> <h3>电影评分统计列表</h3> <ul> {ratingFinal.map((item, index) => ( <li key={index}> 第{index+1}项:评分{item["IMDB Rating"]} * {item["IMDB Votes"]}票 = {item.RatingTotal.toFixed(2)} </li> ))} </ul> </div> ) } export default MovieRatingList;
方案2:useMemo实现(仅用于渲染,代码更精简)
import { useMemo } from 'react'; const movies = Array.from({length: 3021}, () => ({ "IMDB Rating": +(Math.random() * 10).toFixed(1), "IMDB Votes": Math.floor(Math.random() * 10000) })) function MovieRatingList() { // 直接缓存计算结果,依赖变化时自动重新计算 const ratingFinal = useMemo(() => { return movies.map(item => ({ ...item, RatingTotal: item["IMDB Rating"] * item["IMDB Votes"] })) }, [movies]) return ( <div> <h3>电影评分统计列表</h3> <ul> {ratingFinal.map((item, index) => ( <li key={index}> 第{index+1}项:评分{item["IMDB Rating"]} * {item["IMDB Votes"]}票 = {item.RatingTotal.toFixed(2)} </li> ))} </ul> </div> ) } export default MovieRatingList;
补充说明:如果你的
movies数组是通过接口请求获取的,只需要把请求逻辑也放到同一个useEffect中,拿到返回结果后再执行计算逻辑即可,避免重复触发计算。
内容的提问来源于stack exchange,提问作者Beni Djokovic
相关产品推荐
相关产品推荐

