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

如何从useSelector解构属性?解决读取undefined属性的类型错误

从useSelector中解构属性的可行性与问题解决

问题说明

首先明确:可以从useSelector返回的对象中解构属性,你最初的写法是完全可行的:

const { content, loading, loaded } = useSelector(state => ({
  content: state.supply.content,
  loading: state.supply.loading,
  loaded: state.supply.loaded,
}))

但你后续尝试直接解构content内部属性时遇到了Uncaught TypeError: Cannot read properties of undefined (reading 'items')错误,根源在于:

  • state.supply.content的类型是RequestContent | undefined,它可能是RequestItem、RequestCategories、RequestItems三种类型之一,甚至是undefined
  • 你直接用类型断言(state.supply.content as RequestItems)强制将其转为RequestItems,但运行时如果content实际是其他类型或undefined,就会触发读取不存在属性的错误

解决方案

方案1:在Selector中做类型守卫+安全取值

在useSelector的回调里,先通过类型守卫判断content是否为RequestItems类型,再安全提取属性,同时给默认值避免后续使用出错:

const { items, category, totalCountFromServer, loading, loaded } = useSelector(state => {
  const { content, loading, loaded } = state.supply;
  // 用'in'操作符做运行时类型守卫,判断content是否是RequestItems
  const isRequestItems = content && 'items' in content;
  
  return {
    items: isRequestItems ? content.items : [],
    category: isRequestItems ? content.category : null,
    totalCountFromServer: isRequestItems ? content.totalCountFromServer : 0,
    loading,
    loaded,
  };
});

方案2:拆分useSelector调用(更清晰)

如果不需要一次性获取所有值,可以拆分调用,分别取基础状态和处理content属性,逻辑更直观:

// 先取基础状态
const { loading, loaded } = useSelector(state => state.supply);
// 单独取content
const content = useSelector(state => state.supply.content);

// 安全提取content中的属性
const items = content && 'items' in content ? content.items : [];
const category = content && 'items' in content ? content.category : null;
const totalCountFromServer = content && 'items' in content ? content.totalCountFromServer : 0;

关键注意点

  • 避免盲目使用类型断言:TypeScript的类型断言仅作用于编译阶段,不会在运行时校验类型,强行断言会埋下运行时错误隐患
  • 优先用运行时类型守卫:in操作符是处理联合类型的常用方式,能确保你读取的属性确实存在于当前值中
  • 保留shallowEqual:你自定义的useSelector默认使用了shallowEqual,能避免组件因状态浅变化导致的不必要重渲染,这个设置无需修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:07:34