'how to call the useContext function?

im using the useContext from react , i have add boolean state to context but when i use it in the component it's give me typeErro : the setState is not a function

what im doing wrong this is my code ?

// context file

import { createContext, useContext, Dispatch, SetStateAction } from 'react';

interface TasksContextType {
  isSubmitLoading: boolean;
  setIsSubmitLoading: Dispatch<React.SetStateAction<boolean>>;
}

export const TasksContext = createContext({} as TasksContextType);

export const useTasksContext = () => {
  const context = useContext<TasksContextType>(TasksContext);

  if (!context) {
    throw new Error('useTasksContext should be used within a TasksContext');
  }
  return context;
};

the provider file

//provider file 

import React, { FC, useState } from 'react';

import { TasksContext } from './TasksContext';

export const TasksProvider: FC = ({ children }) => {

  const [isSubmitLoading, setIsSubmitLoading] = useState<boolean>(false);

  return (
    <TasksContext.Provider
      value={{
        isSubmitLoading,
        setIsSubmitLoading,
      }}
    >
      {children}
    </TasksContext.Provider>
  );
};

the component where i use the useContext

//component 

const { setIsSubmitLoading, isSubmitLoading } = useTasksContext();

  useEffect(() => {
    setIsSubmitLoading(mutation.isLoading);
  }, [mutation, setIsSubmitLoading]);



Solution 1:[1]

You are checking if you are within your context provider by checking for a falsy value, but since you initialize context with a value ({}) it never will be undefined:

import { createContext, useContext, Dispatch, SetStateAction } from 'react';

interface TasksContextType {
  isSubmitLoading: boolean;
  setIsSubmitLoading: Dispatch<React.SetStateAction<boolean>>;
}

export const TasksContext = createContext({} as TasksContextType); // Here is your problem, change this to:
// createContext<TasksContextType | undefined>();

export const useTasksContext = () => {
  const context = useContext<TasksContextType>(TasksContext); // You can remove the generic here, it will be inferred 

  if (!context) {
    throw new Error('useTasksContext should be used within a TasksContext');
  }
  return context;
};

Now if you try to use the context somewhere you can't, it will throw an error useTasksContext should be used within a TasksContext Or, if you use it within your context it should work ok.

Also note: You should be memoizing your value prop in TasksContext.Provider, otherwise it will be a new object every time and cause all consumers to rerender.

const value = useMemo(() => ({
        isSubmitLoading,
        setIsSubmitLoading,
      }, [isSubmitLoading]) // you can skip setIsSubmitLoading as it is referentially stable

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cal Irvine