Skip to content

Instantly share code, notes, and snippets.

@FederalCircle
Last active November 29, 2023 15:05
Show Gist options
  • Save FederalCircle/8eb6dea3ea1eefd21e85cfe48ecbf706 to your computer and use it in GitHub Desktop.
Save FederalCircle/8eb6dea3ea1eefd21e85cfe48ecbf706 to your computer and use it in GitHub Desktop.
React Context with Typescript

createTypeSafeContext.ts

/**
 * Provides a way to create typesafe contexts without having to check for null
 * initial values all of the time.
 * @see https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/context/
 */
export default function createTypeSafeContext<A extends unknown | null>(): readonly [
    () => A & (unknown | null),
    React.Context<A | undefined>
] {
    const ctx = createContext<A | undefined>(undefined);
    function useCtx() {
        const c = useContext(ctx);
        if (c === undefined) {
            throw new Error('useCtx must be inside a Provider with a value');
        }
        return c;
    }
    return [useCtx, ctx] as const; // 'as const' makes TypeScript infer a tuple
}

Creating the Context

interface FooContextValue {
    foo: string;
}

export const [useFooContext, FooContext] = createTypeSafeContext<FooContextValue>();

export const FooContextProvider = ({ children }: { children?: ReactNode }): JSX.Element => {
    const [foo, setFoo] = useState<string>('');
    return (
        <FooContext.Provider value={{ foo }}>
            {children}
        </FooContext.Provider>
    );
};

Usage in Components

const { foo } = useApplianceContext();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment