Search code examples
reactjstypescriptreact-typescript

'CounterContext' only refers to a type, but is being used as a namespace here


I'm trying use the React Context API in TypeScript but I'm getting the following error:

'CounterContext' only refers to a type, but is being used as a namespace here.

I'm trying to do it by creating a custom hook like so:

import React, { createContext, useContext, useState } from 'react';

type CounterContextProviderProps = {
    children: React.ReactNode;
};

type CounterContextType = {
    counter: number;
    setCounter: React.Dispatch<React.SetStateAction<number>>;
};

export const CounterContext = createContext<CounterContextType | null>(null);

const CounterContextProvider = (
    { children }: CounterContextProviderProps
) => {
    const [counter, setCounter] = useState(0);

    return (
        <CounterContext.Provider
            value={{
                counter,
                setCounter
            }}
        >
            {children}
        </CounterContext.Provider>
    );
}

export default CounterContextProvider;

export const useCounterContext = () => {
    const context = useContext(CounterContext);
    if (!context) {
        throw new Error('useCounterContext must be used within a CounterContextProvider');
    }
    return context;
};

My file is saved as a .tsx file as well, not a .ts.

I've tried changing export const CounterContext = createContext<CounterContext | null>(null); to export const CounterContext = React.createContext<CounterContext | null>(null);. I've changed the file from .tsx to .ts.


Solution

  • TypeScript interprets CounterContext as a type rather than a value in the useContext call. This can happen when there is a type conflict.

    type CounterContext = {
        counter: number;
        setCounter: React.Dispatch<React.SetStateAction<number>>;
    };
    
    export const CounterContext = createContext<CounterContext | null>(null);
    

    Both the type and the context are called CounterContext, make sure to differentiate between them to avoid typescript misinterpretation.

    // changed the type to TCounterContext
    type TCounterContext = {
        counter: number;
        setCounter: React.Dispatch<React.SetStateAction<number>>;
    };
    
    export const CounterContext = createContext<TCounterContext | null>(null);