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

React Router v6下点击用户头像跳转详情页嵌套属性访问报错

问题分析与修复方案

错误原因

"Cannot read properties of undefined (reading 'name')" 错误的核心诱因:

  1. 组件初始化时item为空白对象,直接访问嵌套属性(如item.company.name、item.address.city)会触发链式访问异常
  2. useEffect未监听路由参数id的变化,路由切换时不会重新获取对应用户数据
  3. 未处理找不到匹配用户的场景,list.find返回undefined后直接赋值给item,后续访问属性必然报错

修复步骤

1. 优化初始状态与渲染判断

将item初始状态设为null,添加加载状态判断,避免未加载完成时访问属性:

// 修改状态初始化
const [item, setItem] = useState(null);

// 在组件顶部添加加载判断
if (!item) {
  return <div className="flex justify-center items-center h-screen">加载中...</div>;
}

2. 完善useEffect依赖

将id加入useEffect依赖数组,确保路由参数变化时重新获取数据:

useEffect(() => {
  getItem();
}, [id]); // 新增id作为依赖

3. 处理用户不存在的情况

在getItem函数中判断是否找到用户,未找到时跳转到首页:

const getItem = () => {
  const newItem = list.find((value) => value.id === parseInt(id));
  if (!newItem) {
    navigate('/');
    return;
  }
  setItem(newItem);
};

完整修复后的UserDetail.js代码

import React from 'react';
import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { list } from './Data';

function Profile() {
  const [item, setItem] = useState(null);
  const [show, setShow] = useState(false);

  const { id } = useParams();
  const navigate = useNavigate();

  useEffect(() => {
    getItem();
  }, [id]);

  const getItem = () => {
    const newItem = list.find((value) => value.id === parseInt(id));
    if (!newItem) {
      navigate('/');
      return;
    }
    setItem(newItem);
  };

  const Logout = () => {
    navigate('/');
  };

  if (!item) {
    return <div className="flex justify-center items-center h-screen">加载中...</div>;
  }

  return (
    <div>
      <div className="w-screen h-screen flex gap-10 px-8 pt-3 overflow-x-hidden">
        <div className="flex flex-col w-full">
          <div className="h-[13vh] w-[100%] border-b border-gray-300">
            <div className="flex h-full items-center justify-between">
              <div className="capitalize text-[20px] text-gray-500">
                <p>profile</p>
              </div>

              <div className="relative inline-block text-left mt-5 ml-40" data-headlessui-state>
                <div>
                  <button
                    className="inline-flex w-full justify-center rounded-md bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm focus:outline-none "
                    id="headlessui-menu-button-:r0:"
                    type="button"
                    aria-haspopup="menu"
                    aria-expanded="false"
                    data-headlessui-state="open"
                    aria-controls="headlessui-menu-items-:r1:"
                    onClick={() => setShow(!show)}
                  >
                    <div className="cursor-pointer flex justify-end gap-3 items-center">
                      <img className="rounded-full w-[7%]" src={item.profilepicture} alt={item.id} />
                      <p>{item.name}</p>
                    </div>
                  </button>
                </div>

                {show && (
                  <div
                    className="absolute right-0 z-10 mt-2 w-[20vw] origin-top-right rounded-md bg-white shadow-lg focus:outline-none transform opacity-100 scale-100"
                    aria-labelledby="headlessui-menu-button-:r0:"
                    id="headlessui-menu-items-:r7:"
                    role="menu"
                    tabIndex={0}
                    data-headlessui-state="open"
                  >
                    <div className=" py-1" role="none">
                      <div className="flex flex-col justify-center items-center gap-1 pb-2 " role="none">
                        <img className="rounded-full" src={item.profilepicture} alt="" width="50%" role="none"></img>
                        <p role="none">{item.name}</p>
                        <p className="text-[14px] text-gray-400" role="none">
                          {item.email}
                        </p>
                        <div className="border-t border-gray-300 ">
                          <button className="mt-2 rounded-[20px] px-2 py-1 text-white bg-[#e15b22]" role="none" onClick={Logout}>
                            Sign out
                          </button>
                        </div>
                      </div>
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>

          <div className="block">
            <div className="w-full h-full flex mt-5">
              <div className="border-r border-gray-300 h-full w-[40%]">
                <div className="flex flex-col w-full items-center h-full justify-center">
                  <img className="rounded-full w-[48%]" src={item.profilepicture} alt="" />
                  <p className="text-[16px] font-[400] text-gray-800">{item.name}</p>

                  <div className="flex flex-col gap-2 border-b border-gray-300 py-3">
                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">Username:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.username}</p>
                    </div>

                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">email:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.email}</p>
                    </div>

                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">phoneNumber:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.phone}</p>
                    </div>
                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">website:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.website}</p>
                    </div>
                  </div>

                  <div className="flex flex-col gap-2 py-3">
                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">company:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.company.name}</p>
                    </div>

                    <div className="flex gap-3 items-center justify-center">
                      <p className="text-[16px] font-[400] text-gray-400">bs:</p>
                      <p className="text-[16px] font-[400] text-gray-800">{item.company.bs}</p>
                    </div>
                  </div>
                </div>
              </div>

              <div className="h-full w-[60%]">
                <div className="flex gap-3 items-center justify-center">
                  <p className="text-[16px] font-[400] text-gray-400">address:</p>

                  <p className="text-[16px] font-[400] text-gray-800">{item.address.city}</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

export default Profile;

内容的提问来源于stack exchange,提问作者me at stackoverflow

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:41:45