React无限重渲染问题求助:如何正确使用useEffect与fetch?
React调用PokeAPI的无限循环与渲染错误修复
问题原因分析
- 无限循环错误:
PokemonList组件中直接在函数主体内调用setPokemonsArray,每次组件渲染都会触发状态更新,进而引发新一轮渲染,形成无限循环,导致React抛出Too many re-renders错误。 - 数据未加载时的map报错:App组件中
pokemons初始状态设为空数组,此时pokemons.results为undefined,直接调用map会触发Cannot read properties of undefined (reading 'map')错误。
修复方案
1. 移除冗余局部状态,终止无限循环
PokemonList无需额外维护pokemonsArray状态,直接使用传入的pokemons props即可,消除状态更新引发的循环问题。
2. 处理异步数据加载的边界情况
- 将App组件中
pokemons的初始状态设为null,贴合API返回的对象结构(API返回包含results数组的对象,而非纯数组)。 - 渲染列表前先判断
pokemons.results是否存在,通过条件渲染避免空值调用map。
修改后的代码
App.js
import React from 'react' import PokemonList from "./PokemonList"; function App() { // 初始状态设为null,匹配API返回的对象结构 const [pokemons, setPokemons] = React.useState(null); React.useEffect(() => { console.log('fetch ran') fetch('https://pokeapi.co/api/v2/pokemon') .then(res => res.json()) .then(data => { setPokemons(data); }) }, []) return ( <div> <PokemonList pokemons={pokemons} /> </div> ) } export default App;
PokemonList.js
import React from 'react' export default function PokemonList({ pokemons }) { // 数据未加载时显示加载提示 if (!pokemons?.results) { return <div>加载中...</div> } const pokemonsElements = pokemons.results.map((pokemon) => { return ( <div key={pokemon.name}> <h3>{pokemon.name}</h3> <p>{pokemon.url}</p> <hr /> </div> ) }) return ( <div> {pokemonsElements} </div> ) }
额外说明
- 使用
pokemons?.results可选链操作符,安全访问嵌套属性,避免因pokemons为null或undefined导致的报错。 - 增加加载状态渲染,提升用户体验的同时彻底规避数据未就绪时的渲染错误。
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

