C
Context API
Type-safe React Context for global state management with proper typing for providers and consumers.
Code
typescript
1import React, { createContext, useContext, useState, useCallback, ReactNode } from "react";2 3// Define the shape of your context4interface User {5 id: string;6 name: string;7 email: string;8 role: "admin" | "user" | "guest";9}10 11interface AuthContextType {12 user: User | null;13 isAuthenticated: boolean;14 login: (email: string, password: string) => Promise<void>;15 logout: () => void;16 updateUser: (updates: Partial<User>) => void;17}18 19// Create context with undefined default (will be provided by provider)20const AuthContext = createContext<AuthContextType | undefined>(undefined);21 22// Custom hook for using the context with type safety23function useAuth(): AuthContextType {24 const context = useContext(AuthContext);25 if (context === undefined) {26 throw new Error("useAuth must be used within an AuthProvider");27 }28 return context;29}30 31// Provider component32interface AuthProviderProps {33 children: ReactNode;34}35 36function AuthProvider({ children }: AuthProviderProps) {37 const [user, setUser] = useState<User | null>(null);38 39 const login = useCallback(async (email: string, password: string) => {40 // Simulate API call41 const response = await fetch("/api/login", {42 method: "POST",43 body: JSON.stringify({ email, password }),44 });45 const userData: User = await response.json();46 setUser(userData);47 }, []);48 49 const logout = useCallback(() => {50 setUser(null);51 }, []);52 53 const updateUser = useCallback((updates: Partial<User>) => {54 setUser((prev) => (prev ? { ...prev, ...updates } : null));55 }, []);56 57 const value: AuthContextType = {58 user,59 isAuthenticated: user !== null,60 login,61 logout,62 updateUser,63 };64 65 return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;66}67 68// Theme context example with generics69type Theme = "light" | "dark" | "system";70 71interface ThemeContextType {72 theme: Theme;73 setTheme: (theme: Theme) => void;74 resolvedTheme: "light" | "dark";75}76 77const ThemeContext = createContext<ThemeContextType | undefined>(undefined);78 79function useTheme() {80 const context = useContext(ThemeContext);81 if (!context) throw new Error("useTheme must be used within ThemeProvider");82 return context;83}84 85// Usage in components86function UserProfile() {87 const { user, logout, isAuthenticated } = useAuth();88 const { theme, setTheme } = useTheme();89 90 if (!isAuthenticated) {91 return <p>Please log in</p>;92 }93 94 return (95 <div>96 <h2>Welcome, {user?.name}</h2>97 <p>Role: {user?.role}</p>98 <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>99 Toggle Theme100 </button>101 <button onClick={logout}>Logout</button>102 </div>103 );104}105 106// App with providers107function App() {108 return (109 <AuthProvider>110 <UserProfile />111 </AuthProvider>112 );113}114 115export { AuthProvider, useAuth, ThemeContext, useTheme };Run this example locally
$ npm install react @types/react