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
相关产品推荐
相关产品推荐

