如何为作为Context值的useReducer添加TypeScript类型?
问题:为useReducer返回值的Context添加类型的最佳方式
我想把useReducer的返回值作为StateContext.Provider的值传递,但在使用useContext(StateContext)消费时报错:
Type '[initialStateType, Dispatch] | null' is not an array type
我找到一个临时解决方法:
export const StateContext = createContext([] as unknown as [initialStateType, Dispatch<Action>]);
但不确定这种类型断言是不是最优方案,想知道为作为Context值的useReducer添加类型的最佳方式是什么?
相关代码
stateProvider.tsx
export const StateContext = createContext< [initialStateType, Dispatch<Action>] | null>(null); export const StateProvider = ({ reducer, initialState, children }: StateProviderProps) => { return ( <StateContext.Provider value={useReducer(reducer, initialState)}> {children} </StateContext.Provider> ) }
Product.tsx
export const Product = ({id,title,image,price, rating}: ProductProps) => { const [state,dispatch] = useContext(StateContext); // 报错: Type '[initialStateType, Dispatch<Action>] | null' is not an array type. }
最佳解决方案
1. 移除Context类型中的null,提供合法初始值
当前Context类型包含null,但Provider实际传递的是useReducer返回的合法数组,导致消费时必须处理null分支,触发类型错误。直接给Context提供符合类型的初始值即可:
// 定义空dispatch函数作为默认值 const defaultDispatch: Dispatch<Action> = () => {}; // 用实际的initialState实例和默认dispatch初始化Context export const StateContext = createContext<[initialStateType, Dispatch<Action>]>([ initialState, defaultDispatch ]);
这样Context类型不再包含null,组件中直接解构即可,不会出现类型报错。
2. 封装自定义Hook消费Context
封装自定义Hook可以简化消费逻辑,还能防止组件在Provider外部使用时出现错误:
export const useStateContext = () => { const context = useContext(StateContext); // 确保组件在Provider内部使用 if (!context) { throw new Error('useStateContext 必须在 StateProvider 内部使用'); } return context; };
组件中使用方式:
const [state, dispatch] = useStateContext();
3. 优化StateProvider的泛型类型定义
让StateProvider支持泛型,约束reducer和initialState的类型匹配,提升复用性:
import { Reducer, ReactNode } from 'react'; type StateProviderProps<S, A> = { reducer: Reducer<S, A>; initialState: S; children: ReactNode; }; export const StateProvider = <S, A>({ reducer, initialState, children }: StateProviderProps<S, A>) => { const value = useReducer(reducer, initialState); return ( <StateContext.Provider value={value}> {children} </StateContext.Provider> ); };
内容的提问来源于stack exchange,提问作者Aparichit_Coder
相关产品推荐
相关产品推荐

