0

It's just a simple createContext and useContext code. I struggled a lot until I realised that an if statement is necessary in the useTodoContext function. When I comment out the if statement line, then I get an error. Can you tell me doesn't work the code without the if statement? It doesn't make sense... Without the if statement, this is the error what I get:

Compiled with problems:X

ERROR in src/components/TaskList.tsx:12:11

TS2339: Property 'words' does not exist on type 'Context | null'.
    10 |
    11 | export default function TaskList({ tasks, setTasks }: props) {
  > 12 |   const { words } = useTodoContext();
       |           ^^^^^
    13 |
    14 |   const allowDrop = (e: React.FormEvent) => {
    15 |     e.preventDefault();
import React, { createContext, useContext, useState } from 'react';

type Context = {
  words: string[];
  setWords: React.Dispatch<React.SetStateAction<string[]>>;
};

const TodoContext = createContext<Context | null>(null);

const TodoProvider = ({ children }: { children: React.ReactNode }) => {
  const [words, setWords] = useState<string[]>([]);

  return <TodoContext.Provider value={{ words, setWords }}>{children}</TodoContext.Provider>;
};

const useTodoContext = () => {
  const context = useContext(TodoContext);
  if (!context) throw new Error('Provider not inside'); // without this code line doesn't work
  return context;
};

export { useTodoContext, TodoProvider };
venndi
  • 161
  • 9

1 Answers1

0

Because you've said it can be null and assigned null to it:

const TodoContext = createContext<Context | null>(null);

You can just always give it a value by providing a mock, which would only get accessed if you forgot to wrap your react tree in a provider:

const TodoContext = createContext<Context>({
  words: [],
  setWords: () => {},
});
Dominic
  • 62,658
  • 20
  • 139
  • 163
  • Thank you, yeah it works... but how can have the if statement effect on the code? I mean it goes in the if statement only if the Provider doesn't wrap the element, where I was calling the useTodoContext. Since I wrapped the component, it shouldn't be relevant in my example, it never goes in the if statement. – venndi May 23 '22 at 10:39
  • I'm not sure what you're asking? If your context could potentially be null you would need the if statement with a throw so that anything after definitely has a value. There is no way around that other than what I said, or writing unsafe code (like `return context!` or `return context as TodoConext`) – Dominic May 23 '22 at 11:58