Building Your Learning Module...
Getting things ready for you!
Find videos you like?
Save to resource drawer for future reference!
Passing data with Context is like creating a highway system for your data - instead of stopping at every intersection (component), data flows directly to where it's needed, bypassing unnecessary stops.
First, decide what data you want to pass and how it should be structured. Think about the shape of your data and what functions you'll need to update it.
Best Practice
Group related data together and include update functions in the same context.
Create your Context with meaningful default values. This ensures your components work even without a Provider and helps with testing.
Why Default Values?
Prevents undefined errors and makes your components testable without Providers.
Build a Provider component that manages the state and provides the context value to all child components.
Create a custom hook to make consuming the context easier and provide better error handling.
Use your custom hook in any component to access the data and update functions without prop drilling.
A practical example of passing theme data and toggle function through context
// Step 1: Create Theme Context with default values
const ThemeContext = React.createContext({
theme: 'light',
toggleTheme: () => {}
});
// Step 2: Theme Provider Component
function ThemeProvider({ children }) {
const [theme, setTheme] = React.useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
// Context value object
const value = {
theme,
toggleTheme
};
return (
<ThemeContext.Provider value={value}>
<div className={'theme-' + theme}>
{children}
</div>
</ThemeContext.Provider>
);
}
// Step 3: Custom Hook for easier context consumption
function useTheme() {
const context = React.useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// Step 4: Components consuming the theme context
function Header() {
const { theme, toggleTheme } = useTheme();
return (
<header className="header">
<h1>My Application</h1>
<button onClick={toggleTheme} className="theme-toggle">
{theme === 'light' ? '🌙 Dark' : '☀️ Light'}
</button>
</header>
);
}
function Card({ title, content }) {
return (
<div className="card">
<h3>{title}</h3>
<p>{content}</p>
</div>
);
}
function MainContent() {
return (
<main className="main-content">
<Card
title="Welcome to Context API"
content="This card uses the theme from context!"
/>
<Card
title="Reusable Components"
content="Any component can access the theme without props!"
/>
</main>
);
}
// Step 5: Root App Component
function App() {
return (
<ThemeProvider>
<div className="app">
<Header />
<MainContent />
</div>
</ThemeProvider>
);
}
// ReactDOM integration
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);Loading preview...
Managing user settings with multiple data types and update functions
// Step 1: Create User Preferences Context
const UserPreferencesContext = React.createContext({
preferences: {
language: 'en',
fontSize: 'medium',
notifications: true,
autoSave: false
},
updatePreference: () => {},
resetPreferences: () => {}
});
// Step 2: User Preferences Provider
function UserPreferencesProvider({ children }) {
const [preferences, setPreferences] = React.useState({
language: 'en',
fontSize: 'medium',
notifications: true,
autoSave: false
});
// Update a single preference
const updatePreference = (key, value) => {
setPreferences(prev => ({
...prev,
[key]: value
}));
};
// Reset all preferences to defaults
const resetPreferences = () => {
setPreferences({
language: 'en',
fontSize: 'medium',
notifications: true,
autoSave: false
});
};
const value = {
preferences,
updatePreference,
resetPreferences
};
return (
<UserPreferencesContext.Provider value={value}>
{children}
</UserPreferencesContext.Provider>
);
}
// Step 3: Custom hook for user preferences
function useUserPreferences() {
const context = React.useContext(UserPreferencesContext);
if (!context) {
throw new Error('useUserPreferences must be used within UserPreferencesProvider');
}
return context;
}
// Step 4: Settings Panel Component
function SettingsPanel() {
const { preferences, updatePreference, resetPreferences } = useUserPreferences();
return (
<div className="settings-panel">
<h2>User Preferences</h2>
<div className="setting-group">
<label>Language:</label>
<select
value={preferences.language}
onChange={(e) => updatePreference('language', e.target.value)}
>
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
</select>
</div>
<div className="setting-group">
<label>Font Size:</label>
<select
value={preferences.fontSize}
onChange={(e) => updatePreference('fontSize', e.target.value)}
>
<option value="small">Small</option>
<option value="medium">Medium</option>
<option value="large">Large</option>
</select>
</div>
<div className="setting-group">
<label>
<input
type="checkbox"
checked={preferences.notifications}
onChange={(e) => updatePreference('notifications', e.target.checked)}
/>
Enable Notifications
</label>
</div>
<div className="setting-group">
<label>
<input
type="checkbox"
checked={preferences.autoSave}
onChange={(e) => updatePreference('autoSave', e.target.checked)}
/>
Auto-save
</label>
</div>
<button onClick={resetPreferences} className="reset-btn">
Reset to Defaults
</button>
</div>
);
}
// Step 5: Preferences Display Component
function PreferencesDisplay() {
const { preferences } = useUserPreferences();
return (
<div className="preferences-display">
<h3>Current Preferences</h3>
<div className="preference-item">
<span className="label">Language:</span>
<span className="value">{preferences.language.toUpperCase()}</span>
</div>
<div className="preference-item">
<span className="label">Font Size:</span>
<span className="value">{preferences.fontSize}</span>
</div>
<div className="preference-item">
<span className="label">Notifications:</span>
<span className="value">{preferences.notifications ? '✅ On' : '❌ Off'}</span>
</div>
<div className="preference-item">
<span className="label">Auto-save:</span>
<span className="value">{preferences.autoSave ? '✅ On' : '❌ Off'}</span>
</div>
</div>
);
}
// Step 6: Main App Component
function App() {
return (
<UserPreferencesProvider>
<div className="app">
<div className="container">
<SettingsPanel />
<PreferencesDisplay />
</div>
</div>
</UserPreferencesProvider>
);
}
// ReactDOM integration
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);Loading preview...
// Recommended structure
const contextValue = {
// State data
data: { /* your data here */ },
// Update functions
updateData: (newData) => { /* logic */ },
resetData: () => { /* logic */ },
// Computed values
isLoading: false,
hasError: null,
// Helper functions
validateData: () => { /* logic */ }
};