Back
Syntax
Study
Editor
Mode:
HTML
CSS
JavaScript
PHP
Reset
Run »
HTML / CSS / JS
import { createContext, useContext, useState, type ReactNode } from "react"; // Generic List component interface ListProps<T> { items: T[]; keyExtractor: (item: T) => string | number; renderItem: (item: T) => ReactNode; emptyMessage?: string; } function List<T>({ items, keyExtractor, renderItem, emptyMessage = "No items" }: ListProps<T>) { if (items.length === 0) return <p>{emptyMessage}</p>; return <ul>{items.map(item => <li key={keyExtractor(item)}>{renderItem(item)}</li>)}</ul>; } // Usage — T is inferred as { id: number; name: string } // <List items={users} keyExtractor={u => u.id} renderItem={u => <span>{u.name}</span>} /> // Custom hook with typed tuple return function useLocalStorage<T>(key: string, initialValue: T): [T, (val: T) => void] { const [stored, setStored] = useState<T>(() => { try { const item = localStorage.getItem(key); return item ? (JSON.parse(item) as T) : initialValue; } catch { return initialValue; } }); const setValue = (value: T) => { setStored(value); localStorage.setItem(key, JSON.stringify(value)); }; return [stored, setValue]; } // Typed Context with null-asserting hook interface AuthContextValue { user: { id: number; name: string } | null; login: (email: string, password: string) => Promise<void>; logout: () => void; } const AuthContext = createContext<AuthContextValue | null>(null); export function useAuth(): AuthContextValue { const ctx = useContext(AuthContext); if (!ctx) throw new Error("useAuth must be used within <AuthProvider>"); return ctx; } export function AuthProvider({ children }: { children: ReactNode }) { const [user, setUser] = useState<AuthContextValue["user"]>(null); const login = async (email: string, _pw: string) => { setUser({ id: 1, name: email }); }; const logout = () => setUser(null); return <AuthContext.Provider value={{ user, login, logout }}>{children}</AuthContext.Provider>; }
Result
Open