Context API
Learn to use React Context API for sharing state across multiple components without prop drilling in React Native applications. This is a foundational concept in cross-platform mobile development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React Native experience. Take your time with each section and practice the examples
Context API Basics
Context provides a way to pass data through the component tree without having to pass props down manually at every level. It's perfect for sharing global state like user authentication, theme, or language preferences.
Creating Context
Use React.createContext() to create a context object. The context object contains a Provider component that allows consuming components to subscribe to context changes.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Context Provider
The Provider component accepts a value prop that is passed to all consuming components. When the value changes, all consuming components will re-render.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Context Consumer
Components can consume context using the useContext hook or the Consumer component. The useContext hook is the recommended way in functional components.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Context API Example
import React, { createContext, useContext, useState, useEffect } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Alert } from 'react-native';
// Create Theme Context
const ThemeContext = createContext();
// Theme Provider Component
const ThemeProvider = ({ children }) => {
const [isDarkMode, setIsDarkMode] = useState(false);
const [user, setUser] = useState(null);
const toggleTheme = () => {
setIsDarkMode(prev => !prev);
};
const login = (userData) => {
setUser(userData);
};
const logout = () => {
setUser(null);
};
const theme = {
isDarkMode,
colors: isDarkMode ? {
background: '#1a1a1a',
text: '#ffffff',
primary: '#bb86fc',
surface: '#2d2d2d',
} : {
background: '#ffffff',
text: '#000000',
primary: '#2196F3',
surface: '#f5f5f5',
},
toggleTheme,
user,
login,
logout,
};
return (
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
);
};
// Custom hook to use theme
const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
// Header Component
const Header = () => {
const { isDarkMode, toggleTheme, user } = useTheme();
return (
<View style={[styles.header, { backgroundColor: isDarkMode ? '#2d2d2d' : '#2196F3' }]}>
<Text style={[styles.headerTitle, { color: 'white' }]}>
{user ? `Welcome, ${user.name}!` : 'My App'}
</Text>
<TouchableOpacity onPress={toggleTheme} style={styles.themeButton}>
<Text style={styles.themeButtonText}>
{isDarkMode ? '☀️' : '🌙'}
</Text>
</TouchableOpacity>
</View>
);
};
// Main Content Component
const MainContent = () => {
const { colors, user, login, logout } = useTheme();
const handleLogin = () => {
login({ name: 'John Doe', email: 'john@example.com' });
};
const handleLogout = () => {
logout();
};
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
<Text style={[styles.title, { color: colors.text }]}>
Theme Context Example
</Text>
<View style={[styles.card, { backgroundColor: colors.surface }]}>
<Text style={[styles.cardTitle, { color: colors.text }]}>
Current Theme
</Text>
<Text style={[styles.cardText, { color: colors.text }]}>
{colors.background === '#1a1a1a' ? 'Dark Mode' : 'Light Mode'}
</Text>
</View>
<View style={styles.buttonContainer}>
{user ? (
<TouchableOpacity
style={[styles.button, { backgroundColor: '#f44336' }]}
onPress={handleLogout}
>
<Text style={styles.buttonText}>Logout</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={[styles.button, { backgroundColor: colors.primary }]}
onPress={handleLogin}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
)}
</View>
</View>
);
};
// Main App Component
const App = () => {
return (
<ThemeProvider>
<View style={styles.app}>
<Header />
<MainContent />
</View>
</ThemeProvider>
);
};
const styles = StyleSheet.create({
app: {
flex: 1,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 20,
paddingTop: 40,
},
headerTitle: {
fontSize: 20,
fontWeight: 'bold',
},
themeButton: {
padding: 10,
},
themeButtonText: {
fontSize: 20,
},
container: {
flex: 1,
padding: 20,
},
title: {
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 30,
},
card: {
padding: 20,
borderRadius: 8,
marginBottom: 30,
},
cardTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
cardText: {
fontSize: 16,
},
buttonContainer: {
alignItems: 'center',
},
button: {
paddingHorizontal: 30,
paddingVertical: 15,
borderRadius: 8,
},
buttonText: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
},
});
export default App;