React TypeScript上下文使用报错:Cannot invoke an object which is possibly 'undefined'
嘿,我来帮你搞定这个TypeScript的报错问题!你遇到的这个情况,根源是创建ItemDispatchContext时把初始值设成了undefined,TypeScript就会认定这个dispatch有可能不存在,所以调用它的时候就会抛出那个讨厌的错误。下面给你几个不用每次都写if (dispatch)的解决办法:
方案一:封装自定义Hook做类型与运行时双重校验
你可以写一个专属的自定义Hook,用来获取dispatch,同时在里面判断如果dispatch不存在就抛出错误,这样TypeScript就会知道这个Hook返回的dispatch一定是有效的,而且还能防止有人在Provider外面误用:export function useItemDispatch() { const dispatch = useContext(ItemDispatchContext); if (!dispatch) { throw new Error("useItemDispatch 必须在 ItemContextProvider 内部使用哦"); } return dispatch; }之后在组件里就用这个自定义Hook代替
useContext:export const ItemCol = ({ hit: item }: Props) => { const dispatch = useItemDispatch(); function onItemClick() { dispatch({ type: "UPDATE_SELECTED_ITEM", payload: { selectedItem: item } }); } // ...其他组件逻辑 };方案二:给上下文设置空函数作为初始值
如果你不想写自定义Hook,也可以把ItemDispatchContext的初始值换成一个空函数,这样TypeScript就会认为dispatch永远是一个函数,不会是undefined:export const ItemDispatchContext = createContext<React.Dispatch<Action>>( () => {} // 空函数作为兜底初始值 );这个方案的好处是简单直接,但要注意如果不小心在Provider外面调用dispatch,它只会执行空函数,不会有任何效果,也不会报错,所以适合你能确保所有使用场景都被Provider包裹的情况。
方案三:使用非空断言(不推荐)
还有一种快速解决的方式是用非空断言!告诉TypeScript“这个值肯定不是undefined”,但这种方式跳过了类型检查,万一在Provider外面使用dispatch,运行时会报错,所以不太推荐:export const ItemDispatchContext = createContext<React.Dispatch<Action>>( undefined! );
总的来说,方案一既解决了类型问题,又能做运行时的错误提示,是最稳妥的选择~
备注:内容来源于stack exchange,提问作者TheUnreal

