React组件出现Too many re-renders错误,请求排查解决
解决React无限重渲染问题
问题根源
你代码里的状态更新逻辑直接写在组件顶层,组件每次渲染都会执行pokemon.pokemon.map里的setHp/setAttack等方法,状态更新会触发组件重新渲染,重新渲染又会再次执行这些状态更新,形成无限循环,导致出现Too many re-renders错误。
另外你写的渲染条件逻辑有误:hp || attack || defense || specialAtack || specialDefese || speed === null 这个表达式只要其中任意一个状态不为null,就会返回true,然后渲染null,和你想要的“所有状态都不为null才渲染图表”的逻辑相反。
修复方案
- 用
useEffect包裹状态更新逻辑,仅当pokemon.pokemon变化时才执行,避免每次渲染都触发状态更新。 - 合并多个单独状态为一个对象状态,简化状态管理。
- 修正渲染条件,判断所有属性都存在时才渲染图表。
修改后的代码:
import React, { useState, useEffect } from "react"; import { Chart } from "react-google-charts"; export const StatusChart = ({ pokemon }) => { const [stats, setStats] = useState({ hp: null, attack: null, defense: null, specialAttack: null, specialDefense: null, speed: null }); useEffect(() => { if (!pokemon) return; const newStats = {...stats}; pokemon.forEach(e => { switch (e.stat.name) { case "hp": newStats.hp = e.base_stat; break; case "attack": newStats.attack = e.base_stat; break; case "defense": newStats.defense = e.base_stat; break; case "special-attack": newStats.specialAttack = e.base_stat; break; case "special-defense": newStats.specialDefense = e.base_stat; break; case "speed": newStats.speed = e.base_stat; break; } }); setStats(newStats); }, [pokemon]); const data = [ ["Status", "Value", { role: "style" }], ["HP", stats.hp, "red"], ["Attack", stats.attack, "orange"], ["Defense", stats.defense, "green"], ["Special Attack", stats.specialAttack, "gold"], ["Special Defense", stats.specialDefense, "purple"], ["Speed", stats.speed, "blue"], ]; // 判断所有属性都不为null时渲染图表 const allStatsReady = Object.values(stats).every(val => val !== null); return ( <> {allStatsReady && ( <Chart chartType="ColumnChart" width="100%" height="300px" data={data} /> )} </> ); };
额外说明
- 组件参数改为解构写法
({ pokemon }),避免每次使用都要写pokemon.pokemon,更清晰。 - 合并状态后,状态更新更高效,也更容易维护。
useEffect的依赖数组里加入pokemon,确保只有当传入的pokemon数据变化时,才重新计算状态。
内容的提问来源于stack exchange,提问作者Yuri Jorge Dutra de Araujo
相关产品推荐
相关产品推荐

