Amir-Mousavi
Amir-Mousavi

Reputation: 4561

React, createContext default value problem with useState hook

In my React application with TypeScript, I want to create a context for a component. The createContext shows an error when a default value is not provided. One of the values I want to pass is the setFilters which is a hook dispatcher. How should I provide a default value?

Also, I do not want it optional, to prevent ! from invocation.

    export interface ContextProps {
      filters: FiltersType;
      setFilters: React.Dispatch<React.SetStateAction<FiltersType>>;
    }
    
    export const MyContext = React.createContext<ContextProps>({
      filters: defaultFilters, // imported from constants holder
      setFilters: // <---- What should be here?
    });
    
    const FiltersContext: React.FC<IProps> = (props: IProps) => {
      const [filters, setFilters] = React.useState<FiltersType>(defaultFilters);
    
      return <MyContext.Provider value={{ filters, setFilters }}>{props.children}</MyContext.Provider>;
    };
    
    export default FiltersContext;

Upvotes: 2

Views: 3400

Answers (3)

Diego Segura
Diego Segura

Reputation: 1033

One way would be to just set the function as optional using ? like:

 export interface ContextProps {
      filters: FiltersType;
      setFilters?: React.Dispatch<React.SetStateAction<FiltersType>> | ((fiters: FiltersType) => {});
    }

This way you don't even have to set a default value for the setState functions


Another way would be to add an alternate typing, an empty function that takes the same arguments that your setState would. Then set the default value to that alternate.

So in your example what i'd do is the following (note the underscore _filters to tell ts that the argument will not be used):

   export interface ContextProps {
      filters: FiltersType;
      setFilters: React.Dispatch<React.SetStateAction<FiltersType>> | ((fiters: FiltersType) => {});
    }
    
    export const MyContext = React.createContext<ContextProps>({
      filters: defaultFilters, // imported from constants holder
      setFilters: (_filters: FiltersType) => {}
    });
    
    const FiltersContext: React.FC<IProps> = (props: IProps) => {
      const [filters, setFilters] = React.useState<FiltersType>(defaultFilters);
    
      return <MyContext.Provider value={{ filters, setFilters }}>{props.children}</MyContext.Provider>;
    };
    
    export default FiltersContext;

Upvotes: 0

amik
amik

Reputation: 5909

The default value is used when no context provider is available, so it depends what do you want to do in such situation. You can throw an error, then use setFilters: () => { throw new Error('No FiltersContext available'); }, or silently ignore it, then setFilters: () => {} would do, or whatever you want to do.

Upvotes: 6

Taghi Khavari
Taghi Khavari

Reputation: 6582

You can use just a simple function for its default value like this:

export const MyContext = React.createContext<ContextProps>({
  filters: defaultFilters, // imported from constants holder
  setFilters: () => null
});

Upvotes: 5

Related Questions