React createContext issue in Typescript?

前端 未结 2 568
一个人的身影
一个人的身影 2021-02-02 08:33

So I\'m having a very weird issue with React Context + Typescript.

Working example

In the above example, you can see what I\'m trying to do actually work. Essen

相关标签:
2条回答
  • 2021-02-02 09:12

    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>
      );
    }
    
    0 讨论(0)
  • 2021-02-02 09:15

    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;
    
    0 讨论(0)
提交回复
热议问题