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

React报错TypeError: 无法读取undefined的'userName'属性原因及解决办法

错误原因分析
  • 初始状态类型不匹配:你给blog设置的初始值是数组[],但服务端返回的是对象结构。初始状态下访问blog.blogTitle返回undefined,React渲染undefined属于合法行为不会抛出错误;但访问blog.owner时,数组不存在该属性返回undefined,再访问undefined.userName就会触发TypeError。
  • 加载状态赋值时机错误:你把setDataMounted(true)写在了异步请求的外侧,组件挂载后不等接口返回数据就会立即执行,直接标记数据加载完成,导致渲染逻辑提前访问还没被赋值的嵌套属性。
  • 评论状态更新逻辑错误:直接对blogComments执行push操作属于直接修改state,不会触发组件重渲染,评论列表更新不会生效。

解决方法
  • 修正blog初始值:将初始值改为带有兜底结构的对象,避免嵌套访问报错
// 修改前
const [blog, setBlog] = useState([])
// 修改后
const [blog, setBlog] = useState({ owner: {} })
  • 调整加载状态赋值时机:把setDataMounted(true)移到接口请求的回调内部,确保拿到数据后再标记加载完成,同时把路由参数加入useEffect依赖数组,避免参数变化时不重新请求数据
useEffect(() => {
  APIService.getBlogById(props.match.params.id).then(response => {
    setBlog(response.data)
    setBlogComments([])
    // 拿到数据后再标记加载完成
    setDataMounted(true)
    if (!response.data.comments.includes(null)) {
      response.data.comments.forEach(commentId => {
        APIService.getCommentById(commentId).then(comment => {
          // 不要直接push,用不可变方式更新state
          setBlogComments(prev => [...prev, comment.data])
        })
      })
    }
  })
// 把路由参数加入依赖数组
}, [props.match.params.id])
  • 嵌套属性访问加可选链兜底:访问多层嵌套属性时使用可选链运算符,属性不存在时直接返回undefined不会抛出错误
// 修改前
<p className='blog-owner'>Created By {blog.owner.userName}</p>
// 修改后
<p className='blog-owner'>Created By {blog?.owner?.userName}</p>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:15:03