React-Redux中如何等待API请求完成后再定义常量?
解决React-Redux中Pokemon详情页请求完成前的渲染报错问题
方案1:条件性定义计算常量
在定义moves时先判断数据是否加载完成,不存在则返回空数组;同时在组件最外层判断数据状态,未加载完成时显示加载态:
import { useEffect } from 'react'; import { useParams } from 'react-router-dom'; // React组件名需首字母大写(规范要求) export function PokemonDetail(props) { const { id } = useParams(); const thisPokemon = props.state.entities.pokemon[id]; const movesState = props.state.entities.moves; // 仅当宝可梦数据存在时才处理moves,否则返回空数组 const moves = thisPokemon ? Object.values(movesState).map(val => val.name) : []; useEffect(() => { props.requestSinglePokemon(id); }, [id]); // 数据未加载完成时显示加载提示 if (!thisPokemon) { return <div>Loading...</div>; } return ( <section className="pokemon-detail"> <ul> <figure> <img src={thisPokemon.imageUrl} alt={thisPokemon.name} /> </figure> <li><h2>{thisPokemon.name}</h2></li> <li>Type: {thisPokemon.pokeType}</li> <li>Attack: {thisPokemon.attack}</li> <li>Defense: {thisPokemon.defense}</li> <li>Moves: {moves.join(', ')}</li> </ul> </section> ); }
方案2:使用useMemo延迟计算moves
借助React的useMemo钩子,将thisPokemon和movesState设为依赖项,只有当依赖项变化且数据存在时,才执行moves的计算逻辑,避免初始渲染时的无效计算:
import { useEffect, useMemo } from 'react'; import { useParams } from 'react-router-dom'; export function PokemonDetail(props) { const { id } = useParams(); const thisPokemon = props.state.entities.pokemon[id]; const movesState = props.state.entities.moves; // 依赖thisPokemon,仅当数据存在时才计算moves const moves = useMemo(() => { if (!thisPokemon) return []; return Object.values(movesState).map(val => val.name); }, [thisPokemon, movesState]); useEffect(() => { props.requestSinglePokemon(id); }, [id]); if (!thisPokemon) { return <div>Loading...</div>; } return ( <section className="pokemon-detail"> <ul> <figure> <img src={thisPokemon.imageUrl} alt={thisPokemon.name} /> </figure> <li><h2>{thisPokemon.name}</h2></li> <li>Type: {thisPokemon.pokeType}</li> <li>Attack: {thisPokemon.attack}</li> <li>Defense: {thisPokemon.defense}</li> <li>Moves: {moves.join(', ')}</li> </ul> </section> ); }
方案3:修改Redux初始状态规避空对象问题
如果可以调整Redux的初始状态,把entities.moves的默认值设为空数组而非空对象。这样即使请求未完成,Object.values(movesState)返回的也是空数组,后续map和join操作不会触发报错:
// Redux初始状态示例 const initialState = { entities: { pokemon: {}, moves: [] // 将默认值从{}改为[] } };
修改后原组件中的moves定义无需额外判断,初始渲染时moves就是空数组,join(', ')会返回空字符串,不会引发错误。
内容的提问来源于stack exchange,提问作者agehlot
相关产品推荐
相关产品推荐

