Home > Software engineering >  Using `useContext` with TypeScript - Type 'MyType | null` is not assignable to type 'MyTyp
Using `useContext` with TypeScript - Type 'MyType | null` is not assignable to type 'MyTyp

Time:11-27

I'm working on implementing TypeScript on a small codebase I've been working on and having a few troubles with the above error. I've searched for answers but none seemed to fix the actual issue I was having.

I'm getting the error:

Type 'ContextType | null' is not assignable to type 'ContextType'.

I have tried setting it to null, undefined, and object, and nothing seems to help so I'd appreciate some help with this one!

Store.txt

import { useReducer, createContext, useMemo } from "react";
import { INITIAL_DATA } from './todo/constants';
import { ContextType, ITodo, ACTIONTYPE } from './todo/models';
export const StoreContext = createContext<ContextType | null>(null)

export enum ACTIONS {
  DELETE_TODO = "delete_todo",
  ADD_TODO = "add_todo",
};

const reducer = (state: ITodo, action: ACTIONTYPE) => {
  switch (action.type) {
    case ACTIONS.DELETE_TODO:
      return [...action.payload];
    case ACTIONS.ADD_TODO:
      return action.payload;
    default:
      return state;
  }
};

interface Props {
  children: React.ReactNode;
}

export const StoreProvider = ({ children }: Props) => {
  const [state, dispatch] = useReducer(reducer, INITIAL_DATA);
  const contextValue: ContextType = useMemo(() => {
    return { state, dispatch };
  }, [state, dispatch]);

  return (
    <StoreContext.Provider value={contextValue}>
      {children}
    </StoreContext.Provider>
  );
};

Component.tsx

import { useContext } from 'react';

import { StoreContext, ACTIONS } from '../../../store';
import { ContextType } from '../../models'


export const AddTodo = () => {
  const { state, dispatch }: ContextType = useContext(StoreContext);

  const validateFirstStep = async () => {
    return await isValid(firstStepForm);
  }

  const closeDrawer = () => {
    onClose();
  }

  const handleSubmit = async () => {
    const newTodoEntry = { /** todo **/ }
    const newData = [...state, newTodoEntry];

    dispatch({ type: ACTIONS.ADD_TODO, payload: newData });
  }

  return (
    <div>
     { /* Something Todo happens here */ }
    </div>
  )
}

Models.tsx

import { ACTIONS } from '../../store';

export type ITodos = {
  id: string;
  todoName: string;
  todoType: string;
}[];

export type ContextType = {
  state: ITodos;
  dispatch: React.Dispatch<ACTIONTYPE>;
}

export type ACTIONTYPE =
  | { type: ACTIONS.ADD_TODO, payload: ITodos }
  | { type: ACTIONS.DELETE_TODO; payload: ITodos }

CodePudding user response:

You need to provide default context value in case of there is no provider higher in the react tree;

export const StoreContext = createContext<ContextType>({todos: [], dispatch: () => {}})
  • Related