使用Redux获取API数据时刷新页面出现stats未定义的TypeError问题求助
解决Redux刷新时报"Cannot read properties of undefined (reading 'stats')"的问题
问题出在哪
- Redux初始状态没给够默认结构:刷新页面后Redux store会重置,要是
coinsState.coins初始值没包含data.stats这层结构,访问coins.data.stats时肯定会踩undefined的坑。 - loading初始值设错了:如果初始state里
loading是false,组件一上来就会去渲染数据,但这时候API请求还没开始,coins根本没数据,直接报错。 - 没做深层属性的安全访问:就算loading变成
false,万一API返回的数据结构不对(比如缺了data字段),照样会崩。
怎么解决
1. 先把Redux初始状态改对
在你的coins reducer里,给coins预设好完整的空结构,保证每一层都有兜底:
// coinsReducer.js const initialState = { coins: { data: { stats: {} } }, // 提前把结构搭好,避免访问undefined loading: true, // 一开始就设成加载中,让组件先显示loading error: null // 加个错误状态,处理请求失败的情况 }; const coinsReducer = (state = initialState, action) => { switch(action.type) { case 'FETCH_COINS_REQUEST': return { ...state, loading: true }; case 'FETCH_COINS_SUCCESS': return { ...state, loading: false, coins: action.payload }; case 'FETCH_COINS_FAILURE': return { ...state, loading: false, error: action.payload }; default: return state; } }; export default coinsReducer;
2. 组件里加安全访问和错误处理
- 用**可选链
?.**来访问深层属性,就算某一层是undefined也不会崩溃。 - 加上错误状态判断,请求失败时给用户提示。
- 给数值加个默认值
|| 0,确保millify能正常工作。
修改后的组件代码:
import React, { useEffect } from 'react'; import { useSelector, useDispatch} from 'react-redux'; import { Link } from 'react-router-dom'; import millify from 'millify'; //Redux import { fetchCoins } from "../../redux/coins/coinsAction"; const Homepage = () => { const dispatch = useDispatch(); const { coins, loading, error } = useSelector(state => state.coinsState); useEffect(() => { dispatch(fetchCoins()); }, [dispatch]) // 加上dispatch依赖,避免ESLint警告 if (loading) return <h1>Loading...</h1>; if (error) return <h1>加载数据失败:{error.message}</h1>; // 先把stats取出来,没有的话用空对象兜底 const stats = coins?.data?.stats || {}; return ( <div> <h2>全球加密货币统计</h2> <div> <h5>加密货币总数</h5> <span>{millify(stats.total || 0)}</span> <h5>交易所总数</h5> <span>{millify(stats.totalExchanges || 0)}</span> <h5>总市值</h5> <span>{millify(stats.totalMarketCap || 0)}</span> <h5>24小时总交易量</h5> <span>{millify(stats.total24hVolume || 0)}</span> <h5>交易市场总数</h5> <span>{millify(stats.totalMarkets || 0)}</span> </div> </div> ); }; export default Homepage;
3. 补全useEffect的依赖
给useEffect加上dispatch作为依赖,这不会导致重复渲染(React 18+里dispatch是稳定的引用),还能避免ESLint警告。
为啥之前的loading没起作用?
要是你初始loading设成了false,刷新页面时组件会直接跳去渲染数据的分支,但这时候API请求还在跑,coins还是初始的空值,肯定会报错。把初始loading设为true,就能保证请求完成前不会去碰数据。
内容的提问来源于stack exchange,提问作者Milad.eb96
相关产品推荐
相关产品推荐

