Um contexto de tema com alternância para modo escuro
Crie um ThemeContext que armazene o esquema de cores atual, disponibilize uma função de alternância e aplique as cores do tema aos componentes em todo o aplicativo.
Um contexto de tema com alternância para modo escuro é uma aula grátis de React Native Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Native Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Native Academy inclui 4 aulas no total.
Partes desta aula ainda não foram traduzidas e aparecem em inglês.
Why a Theme Context?
A theme context centralizes color and typography values so that every component in the app reads from a single source of truth. When the user switches between light and dark mode, updating the context value triggers a re-render of all consuming components with the new colors — no prop drilling or manual updates required.
Defining Light and Dark Theme Objects
Start by defining two theme objects with the same keys. Using identical keys for both themes means every component can apply a color without knowing which mode is active — it just reads from the current theme object and both themes handle the rest.
export const lightTheme = {
background: '#ffffff',
text: '#1a1a2e',
card: '#f5f5f5',
primary: '#6200ee',
border: '#e0e0e0',
};
export const darkTheme = {
background: '#1a1a2e',
text: '#e8e8f0',
card: '#16213e',
primary: '#bb86fc',
border: '#333355',
};Creating the ThemeContext
Create a ThemeContext that holds the current theme object and a toggle function. The default value mirrors the shape of what the Provider will supply, making it safe to destructure in consumers even if the Provider is accidentally missing in tests.
import { createContext, useContext, useState } from 'react';
import { lightTheme, darkTheme } from './themes';
export const ThemeContext = createContext({
theme: lightTheme,
isDark: false,
toggleTheme: () => {},
});Building the ThemeProvider
The ThemeProvider manages a boolean isDark state and derives the active theme object from it. The toggleTheme function flips the boolean. Memoize the context value with useMemo so that a new object reference is only created when isDark actually changes.
export function ThemeProvider({ children }) {
const [isDark, setIsDark] = useState(false);
const value = useMemo(() => ({
theme: isDark ? darkTheme : lightTheme,
isDark,
toggleTheme: () => setIsDark((d) => !d),
}), [isDark]);
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
}A useTheme Custom Hook
Export a useTheme hook that wraps useContext(ThemeContext). Components call useTheme() for a clean, descriptive import instead of remembering to pass the context object. The hook also throws a helpful error if called outside a ThemeProvider.
export function useTheme() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('useTheme must be inside ThemeProvider');
return ctx;
}Applying Theme Colors to a Component
Any component that reads from useTheme will automatically display the correct colors for the current mode. Pass the theme colors into inline styles or StyleSheet styles. When the theme toggles, all consuming components re-render with the new values.
function Card({ title, body }) {
const { theme } = useTheme();
return (
<View style={{
backgroundColor: theme.card,
borderColor: theme.border,
borderWidth: 1,
borderRadius: 8,
padding: 16,
}}>
<Text style={{ color: theme.text, fontWeight: 'bold' }}>{title}</Text>
<Text style={{ color: theme.text }}>{body}</Text>
</View>
);
}A Toggle Switch in the Settings Screen
Add a dark mode switch to the settings screen. The Switch component's value is isDark from the theme context, and onValueChange calls toggleTheme. No local state needed — the toggle directly controls the global theme state.
function SettingsScreen() {
const { isDark, toggleTheme, theme } = useTheme();
return (
<View style={{ backgroundColor: theme.background, flex: 1, padding: 24 }}>
<Text style={{ color: theme.text }}>Dark Mode</Text>
<Switch
value={isDark}
onValueChange={toggleTheme}
trackColor={{ true: theme.primary }}
/>
</View>
);
}Persisting the Theme Preference
Save the user's theme preference to AsyncStorage so it survives app restarts. In ThemeProvider, load the saved preference in a useEffect on mount and initialize state accordingly. Save the new value in toggleTheme whenever the user switches modes.
export function ThemeProvider({ children }) {
const [isDark, setIsDark] = useState(false);
useEffect(() => {
AsyncStorage.getItem('theme').then((saved) => {
if (saved === 'dark') setIsDark(true);
});
}, []);
const toggleTheme = () => {
const next = !isDark;
setIsDark(next);
AsyncStorage.setItem('theme', next ? 'dark' : 'light');
};
// ...
}Respecting the System Theme
React Native's useColorScheme hook returns the device's current color scheme ('light' or 'dark'). You can use this as the default theme instead of always starting in light mode. If the user has not explicitly set a preference, respecting the system setting gives the best out-of-the-box experience.
import { useColorScheme } from 'react-native';
function ThemeProvider({ children }) {
const systemScheme = useColorScheme();
const [isDark, setIsDark] = useState(systemScheme === 'dark');
// ...
}Applying Theme to Navigation Header
The navigation header can also respond to theme changes. Pass a function to screenOptions on the navigator that reads from the theme context and returns header style options. When the theme changes, the navigator re-evaluates the options and updates the header colors accordingly.
function AppStack() {
const { theme } = useTheme();
return (
<Stack.Navigator
screenOptions={{
headerStyle: { backgroundColor: theme.card },
headerTintColor: theme.text,
}}
>
<Stack.Screen name='Home' component={HomeScreen} />
</Stack.Navigator>
);
}Preventing Flicker on Theme Load
When loading the saved theme from AsyncStorage on startup, there is a brief moment before the preference is restored. Prevent a flash of the wrong theme by showing a splash screen or delaying navigation until the theme is loaded. Use an isThemeReady state in the provider and render null until it is true.
const [isDark, setIsDark] = useState(false);
const [ready, setReady] = useState(false);
useEffect(() => {
AsyncStorage.getItem('theme').then((saved) => {
if (saved === 'dark') setIsDark(true);
setReady(true);
});
}, []);
if (!ready) return null; // prevent flashQuick Check
Test your understanding of theme context and dark mode from this lesson.
Lesson Recap
In this lesson you learned: define separate light and dark theme objects with matching keys, provide both the active theme and a toggleTheme function through context, and persist the theme preference to AsyncStorage and restore it on app startup. Next up we explore avoiding context performance pitfalls.
Perguntas Frequentes
A aula “Um contexto de tema com alternância para modo escuro” é grátis?
Sim — o texto completo de “Um contexto de tema com alternância para modo escuro” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Native Academy, atualize para CoddyKit PRO. O curso de React Native Academy inclui 4 aulas no total.
O que vou aprender em “Um contexto de tema com alternância para modo escuro”?
Crie um ThemeContext que armazene o esquema de cores atual, disponibilize uma função de alternância e aplique as cores do tema aos componentes em todo o aplicativo. Você pratica React Native Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar React Native Academy?
Nenhuma experiência prévia é necessária. React Native Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “Um contexto de tema com alternância para modo escuro”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de React Native Academy?
Sim. Cada aula de React Native Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Criando e fornecendo um contexto
- Consumindo contexto com useContext
- Um contexto de tema com alternância para modo escuro
- Evitando problemas de desempenho do contexto