iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Context

Context shares state across a component tree without prop drilling. Wrap with a Provider; read with useContext. Use it for theme, auth, locale — values that don’t change every frame.

Theme + Auth context, the typed way

EXAMPLE
import { createContext, useContext, useState, useEffect } from 'react';
import { ColorSchemeName, useColorScheme } from 'react-native';

// 1) Auth context — typed value, runtime guard
type AuthState = {
    user:   { uid: string; email: string } | null;
    signIn: (email: string, pw: string) => Promise<void>;
    signOut: () => Promise<void>;
};

const AuthCtx = createContext<AuthState | null>(null);

export function AuthProvider({ children }) {
    const [user, setUser] = useState(null);
    useEffect(() => firebase.auth.onAuthStateChanged(setUser), []);
    const value: AuthState = {
        user,
        signIn:  (email, pw) => firebase.auth.signIn(email, pw),
        signOut: ()          => firebase.auth.signOut(),
    };
    return <AuthCtx.Provider value={value}>{children}</AuthCtx.Provider>;
}

export function useAuth() {
    const ctx = useContext(AuthCtx);
    if (!ctx) throw new Error('useAuth must be inside an AuthProvider');
    return ctx;
}

// 2) Theme context — read system preference, allow override
type Theme = 'light' | 'dark';
const ThemeCtx = createContext<{ theme: Theme; setTheme: (t: Theme) => void } | null>(null);

export function ThemeProvider({ children }) {
    const system = useColorScheme();
    const [override, setOverride] = useState<Theme | null>(null);
    const theme = override ?? (system ?? 'light');
    return (
        <ThemeCtx.Provider value={{ theme, setTheme: setOverride }}>
            {children}
        </ThemeCtx.Provider>
    );
}

export const useTheme = () => useContext(ThemeCtx)!;

// 3) Compose at the root
export default function App() {
    return (
        <AuthProvider>
            <ThemeProvider>
                <Navigation />
            </ThemeProvider>
        </AuthProvider>
    );
}

Why it matters

Context re-renders EVERY consumer when the value changes. For fast-changing state (form values, scroll position) reach for Zustand / Jotai — they re-render only consumers that read the changed slice.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
const Theme = createContext('light');
// provider
<Theme.Provider value="dark"><App /></Theme.Provider>
// consumer
const theme = useContext(Theme);
Try it Yourself »

Discussion

Loading…