Redux action.type报错Cannot read properties of undefined排查
这个报错和你写的reducer逻辑本身没关系,纯粹是useSelector用错了。
你对reducer的认知是对的:reducer只会被Redux store内部调用,正常场景下传入的action永远是带type字段的合法对象,不可能是undefined,这也是官方示例里从来不会给action加可选链的原因。
真正触发报错的是这行代码:const mySelector = useSelector(myReducer);useSelector要接收的是状态选择函数,它的执行逻辑很简单:组件首次渲染、每次store状态更新的时候,会把整个Redux根state作为第一个参数传给你传进去的选择函数,根本不会传第二个参数。你把reducer直接塞给useSelector之后,选择器执行的时候就相当于调用myReducer(整个根state),第二个形参action就是undefined,这时候你访问action.type,当然会抛「Cannot read properties of undefined (reading 'type')」的错误。
至于你写action?.type的时候程序能跑,纯粹是歪打正着:可选链碰到undefined的action直接返回undefined,switch匹配不到任何case就走default分支,把传进来的第一个参数(也就是整个根state)原封不动返回,刚好你的state结构和你预期要取的内容对上了,看起来就像功能正常,本质是错误用法碰出来的巧合,根本不是正确实现。
- 先确认你创建store的时候已经把
myReducer正确注册进去了,参考写法:
import { configureStore } from '@reduxjs/toolkit' import { myReducer } from './reducer' export const store = configureStore({ reducer: { // 这个key可以自定义,对应后面选择器取数的路径 profile: myReducer } })
- 改掉useSelector的错误传参,不要直接传reducer,写个简单的选择函数从根state里摘出你需要的片段就行:
const myDispatch = useDispatch(); // 错误写法:const mySelector = useSelector(myReducer); // 如果你在store里给reducer配的key是profile,就这么写 const profileState = useSelector(state => state.profile);
- 把reducer里的
action?.type改回标准的action.type就行,不需要加可选链。改完之后reducer只会被Redux内部调用,永远能拿到合法的action参数,不会再出这个类型错误:
export function myReducer(state = initialState, action) { switch (action.type) { case NAME_UPDATED: return { ...state, name: action.payload }; default: return state; } }
- 最后把模板里读状态的代码对应改下就完事:
<p> The Current value of <code>name</code> in the store is: <code>{profileState.name}</code>. </p> <button onClick={() => myDispatch(updateProfile('Updated Name'))}> Update Name </button>
内容的提问来源于stack exchange,提问作者Chaudhry Talha

