Expo+React Native集成Redux时导入photosReducer报TypeError错误
报错根因
你遇到的报错完全来自自定义类对JS全局内置对象的遮蔽覆盖:
- 你的自定义数据模型类直接命名为
Object,在reducer文件中通过import Object from "../models/object"导入后,当前模块作用域内的Object引用会被直接替换为你写的自定义类,而不再是JS运行时原生提供的全局内置Object构造器。 - Redux在初始化store、做状态不可变校验的过程中,会在当前模块的作用域内调用原生
Object.defineProperty实现状态代理。此时拿到的Object是你的自定义类,这个类本身没有defineProperty静态方法,因此直接抛出TypeError: undefined is not an object (evaluating 'Object.defineProperty')。 - 因为导入逻辑在应用启动阶段就会执行,所以报错会在你刚导入photosReducer、执行combineReducers时就触发,和Redux中间件、导航配置没有关系。
修复步骤
- 重命名自定义模型类,避开JS内置全局名称
不要用Object作为自定义类的名字,结合这个类存储照片数据的实际用途,可以重命名为Photo,对应修改模型文件:// 建议将原来的models/object.js重命名为models/Photo.js class Photo { constructor(id, title) { this.id = id; this.title = title; } } export default Photo; - 修改reducer的导入和实例化逻辑
替换掉原来导入自定义Object的代码,同时修复原有reducer的不可变更新隐患:// store/photo-reducer.js import { ADD_PHOTO } from "./photo-actions"; // 替换原有的Object导入 import Photo from "../models/Photo"; const initialState = { photos: [], }; export default (state = initialState, action) => { switch (action.type) { case ADD_PHOTO: const newPhoto = new Photo( new Date().toString(), action.photoData.title ); return { // 补充原state展开逻辑,避免后续新增state字段时被意外覆盖丢失 ...state, photos: state.photos.concat(newPhoto), }; default: return state; } };
排查提示
JS内置的全局构造器(包括Object、Array、Function、String等)绝对不能作为自定义类名、变量名使用,这类名称遮蔽导致的报错往往距离错误触发点很远,很难通过堆栈定位到根因。
内容的提问来源于stack exchange,提问作者Timo
相关产品推荐
相关产品推荐

