You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Redux获取API数据时刷新页面出现stats未定义的TypeError问题求助

解决Redux刷新时报"Cannot read properties of undefined (reading 'stats')"的问题

问题出在哪

  1. Redux初始状态没给够默认结构:刷新页面后Redux store会重置,要是coinsState.coins初始值没包含data.stats这层结构,访问coins.data.stats时肯定会踩undefined的坑。
  2. loading初始值设错了:如果初始state里loading是false,组件一上来就会去渲染数据,但这时候API请求还没开始,coins根本没数据,直接报错。
  3. 没做深层属性的安全访问:就算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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:48:23