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

React组件仅首次正常显示,刷新后报TypeError错误求助

问题分析

报错TypeError: Cannot read properties of undefined (reading 'last')的核心原因很明确:

  • 组件初始渲染时,user的初始值是空数组[],此时直接访问user[0].last等同于访问undefined.last,必然触发报错。
  • useEffect里的请求是异步的,组件会先完成第一次渲染,这时候请求还没返回,user还是初始的空数组状态。

另外还有个隐藏问题:你的useEffect依赖数组是空的,但内部用到了username参数,当username变化时(比如从其他用户页面跳转过来),不会重新发起请求,这会导致数据不更新。

解决方案

推荐结合以下几种方式修复:

1. 增加状态管理与条件渲染

通过加载、错误状态控制渲染流程,避免访问未定义的属性:

import React from "react";
import { useParams } from "react-router-dom";
import { useState, useEffect } from "react";

const SingleUser = () => {
  const [user, setUser] = useState(null); // 初始设为null,更直观区分无数据状态
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const { username } = useParams();

  useEffect(() => {
    const getSingleUser = async () => {
      try {
        setLoading(true);
        const res = await fetch(
          `https://api.chess.com/pub/player/${username}/stats`
        );
        if (!res.ok) throw new Error("用户数据请求失败");
        const data = await res.json();
        const heroesArray = Object.values(data);
        setUser(heroesArray);
      } catch (err) {
        setError(err.message);
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    getSingleUser();
  }, [username]); // 将username加入依赖,确保参数变化时重新请求

  // 加载中状态
  if (loading) return <div>加载用户数据中...</div>;
  // 错误状态兜底
  if (error) return <div>出错了:{error}</div>;
  // 无数据时的兜底
  if (!user || user.length === 0) return <div>未找到该用户的棋力数据</div>;

  return (
    <section>
      <div>
        <h1>Rapid Chess</h1>
        <p>Current Rating: {user[0].last.rating}</p>
        <p>Best Rating: {user[0].best.rating}</p>
        <div>
          <p>Wins: {user[0].record.win}</p>
          <p>Losses: {user[0].record.loss}</p>
          <p>Draws: {user[0].record.draw}</p>
        </div>
      </div>
    </section>
  );
};

export default SingleUser;

2. 用可选链快速兜底(简化版)

如果不想写过多状态判断,可以直接在模板里用可选链操作符?.避免报错,同时给默认值:

// 仅修改渲染部分
return (
  <section>
    <div>
      <h1>Rapid Chess</h1>
      <p>Current Rating: {user[0]?.last?.rating || "N/A"}</p>
      <p>Best Rating: {user[0]?.best?.rating || "N/A"}</p>
      <div>
        <p>Wins: {user[0]?.record?.win || 0}</p>
        <p>Losses: {user[0]?.record?.loss || 0}</p>
        <p>Draws: {user[0]?.record?.draw || 0}</p>
      </div>
    </div>
  </section>
);

3. 必须修正useEffect依赖

不管用哪种方案,都要把username加入useEffect的依赖数组,否则参数变化时不会重新请求数据,会导致页面展示旧用户的信息。

内容的提问来源于stack exchange,提问作者jey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 01:52:43