Skip to main content

useTrackedContext

Track Context API changes with automatic provider and consumer monitoring.

Overview​

useTrackedContext and createTrackedProvider help you debug Context API by tracking when context values change and which components consume them.

API​

// Create a tracked provider
const TrackedProvider = createTrackedProvider(YourContext, 'contextLabel');

// Use tracked context in components
const value = useTrackedContext(YourContext, 'contextLabel');

Basic Example​

import { createContext } from 'react';
import { useTrackedContext, createTrackedProvider } from 'react-dev-debugger';

interface ThemeContext {
theme: 'light' | 'dark';
toggleTheme: () => void;
}

const ThemeContext = createContext<ThemeContext>({
theme: 'light',
toggleTheme: () => {},
});

// Create tracked provider
const TrackedThemeProvider = createTrackedProvider(ThemeContext, 'theme');

function App() {
const [theme, setTheme] = useState<'light' | 'dark'>('light');

const value = {
theme,
toggleTheme: () => setTheme(t => t === 'light' ? 'dark' : 'light'),
};

return (
<TrackedThemeProvider value={value}>
<YourApp />
</TrackedThemeProvider>
);
}

function ThemedButton() {
// Track context consumption
const { theme, toggleTheme } = useTrackedContext(ThemeContext, 'theme');

return (
<button onClick={toggleTheme}>
Current theme: {theme}
</button>
);
}

Live Playground​

Context Provider

Theme Settings
const TrackedProvider = createTrackedProvider(
  ThemeContext, 
  'theme'
);

<TrackedProvider value={{ theme, language, notifications }}>
  <App />
</TrackedProvider>
Consumer Component
Theme: light
Language: en
Notifications: Enabled
function ThemedComponent() {
  const { theme, language } = useTrackedContext(
    ThemeContext, 
    'theme'
  );
  
  return <div>Theme: {theme}</div>;
}
Current Context Value
{ "theme": "light", "language": "en", "notifications": true }

Context Updates

No context updates yet

Advanced Examples​

Multi-value Context​

interface AppContext {
user: User | null;
settings: Settings;
notifications: Notification[];
}

const AppContext = createContext<AppContext>({
user: null,
settings: defaultSettings,
notifications: [],
});

const TrackedAppProvider = createTrackedProvider(AppContext, 'appContext');

function AppProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
const [settings, setSettings] = useState(defaultSettings);
const [notifications, setNotifications] = useState<Notification[]>([]);

const value = { user, settings, notifications };

return (
<TrackedAppProvider value={value}>
{children}
</TrackedAppProvider>
);
}

Auth Context​

interface AuthContext {
isAuthenticated: boolean;
user: User | null;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
}

const AuthContext = createContext<AuthContext | undefined>(undefined);

const TrackedAuthProvider = createTrackedProvider(AuthContext, 'auth');

function useAuth() {
const context = useTrackedContext(AuthContext, 'auth');
if (!context) {
throw new Error('useAuth must be used within AuthProvider');
}
return context;
}

I18n Context​

interface I18nContext {
language: string;
translations: Record<string, string>;
setLanguage: (lang: string) => void;
t: (key: string) => string;
}

const I18nContext = createContext<I18nContext>({
language: 'en',
translations: {},
setLanguage: () => {},
t: (key) => key,
});

const TrackedI18nProvider = createTrackedProvider(I18nContext, 'i18n');

function I18nProvider({ children }: { children: React.ReactNode }) {
const [language, setLanguage] = useState('en');
const [translations, setTranslations] = useState({});

const t = (key: string) => translations[key] || key;

const value = { language, translations, setLanguage, t };

return (
<TrackedI18nProvider value={value}>
{children}
</TrackedI18nProvider>
);
}

Debugging Features​

Provider Updates​

See when context values change:

  • Which properties changed
  • Old vs new values
  • Which provider triggered the update

Consumer Tracking​

Identify which components consume context:

  • Component names
  • Which context properties they use
  • Re-render frequency

Dependency Graph​

Visualize context flow:

  • Provider → Consumer relationships
  • Context propagation tree
  • Performance bottlenecks

Best Practices​

✅ Do's​

  • Use descriptive labels: 'authContext' instead of 'ctx'
  • Split large contexts: Multiple small contexts are easier to track
  • Memoize context values: Prevent unnecessary updates
  • Use custom hooks: Wrap context consumption in custom hooks

❌ Don'ts​

  • Don't pass objects directly: Memoize to prevent re-renders
  • Don't put everything in one context: Split by domain
  • Don't forget dependencies: Include all used values

Performance Optimization​

function OptimizedProvider({ children }: { children: React.ReactNode }) {
const [state, setState] = useState(initialState);

// Memoize context value
const value = useMemo(() => ({
state,
updateState: setState,
}), [state]);

return (
<TrackedProvider value={value}>
{children}
</TrackedProvider>
);
}

TypeScript Support​

Full type safety:

interface MyContext {
value: string;
setValue: (v: string) => void;
}

const MyContext = createContext<MyContext>({
value: '',
setValue: () => {},
});

// Type-safe provider
const TrackedProvider = createTrackedProvider(MyContext, 'myContext');

// Type-safe consumer
function MyComponent() {
const { value, setValue } = useTrackedContext(MyContext, 'myContext');
// value: string
// setValue: (v: string) => void
}

Next Steps​