React createContext issue in Typescript?
It appears defaultValue
value for React.createContext
is expected to be of type:
interface IContextProps { state: IState; dispatch: ({type}:{type:string}) => void;}
Once Context
object is created for this type, for example like this:
export const AdminStore = React.createContext({} as IContextProps);
Provider React component should no longer complain about the error.
Here is the list of changes:
admin-store.tsx
import React, { useReducer } from "react";import { initialState, IState, reducer } from "./reducer";interface IContextProps { state: IState; dispatch: ({type}:{type:string}) => void;}export const AdminStore = React.createContext({} as IContextProps);export function AdminStoreProvider(props: any) { const [state, dispatch] = useReducer(reducer, initialState); const value = { state, dispatch }; return ( <AdminStore.Provider value={value}>{props.children}</AdminStore.Provider> );}
I had a fun time with this so I figured I'd share what I came up with.
The SidebarProps
represent the context's state. Everything else, besides the reducer actions, can essentially be used as is.
Here is a nice article explaining the exact same workaround (Not in TypeScript) : Mixing Hooks and Context Api
import React, { createContext, Dispatch, Reducer, useContext, useReducer } from 'react';interface Actions { type: string; value: any;}interface SidebarProps { show: boolean; content: JSX.Element | null;}interface SidebarProviderProps { reducer: Reducer<SidebarProps, Actions>; initState: SidebarProps;}interface InitContextProps { state: SidebarProps; dispatch: Dispatch<Actions>;}export const SidebarContext = createContext({} as InitContextProps);export const SidebarProvider: React.FC<SidebarProviderProps> = ({ reducer, initState, children }) => { const [state, dispatch] = useReducer(reducer, initState); const value = { state, dispatch }; return ( <SidebarContext.Provider value={value}> {children} </SidebarContext.Provider> );};export const useSidebar = () => useContext(SidebarContext);const SidebarController: React.FC = ({ children }) => { const initState: SidebarProps = { show: false, content: null }; const reducer: Reducer<SidebarProps, Actions> = (state, action) => { switch (action.type) { case 'setShow': return { ...state, show: action.value }; case 'setContent': return { ...state, content: action.value }; default: return state; } }; return ( <SidebarProvider reducer={reducer} initState={initState}> {children} </SidebarProvider> );};export default SidebarController;