My application needs a color themes providing and I am trying to implement a Theme Providing component using a React Context, but it does not work. I can't figure out how to get the theme prop object from the Theme Provider's Context and how can I call the updateTheme function that is state of Theme Provider? This is my code:
ThemeProvider
import React from "react";
import { LightTheme, DarkTheme } from '../themes'
const Context = React.createContext();
export class ThemeProvider extends React.Component {
state = {
theme: LightTheme,
updateTheme: (theme) => {
this.setState({ theme: theme })
}
}
render() {
const { theme } = this.state
return (
<Context.Provider value={this.state} theme={theme} >
{ this.props.children }
</Context.Provider>
)
}
}
export default ThemeProvider;
App
import React from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { HomeScreen } from './screens';
import { NavBar, ThemeProvider } from './components';
const Stack = createStackNavigator();
const App: () => React$Node = () => {
return (
<ThemeProvider>
<NavigationContainer>
<StatusBar barStyle="dark-content" />
<NavBar />
<Stack.Navigator
screenOptions={{
headerShown: false
}}
>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
</ThemeProvider>
);
};
export default App;
Navbar (this component have to get the theme prop from the ThemeProvider to change it's color)
import React from 'react';
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
StatusBar,
} from 'react-native';
import { Container, Header, Left, Body, Right, Button, Title } from 'native-base';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { Layout } from '../constants';
class NavBar extends React.Component {
static contextType = ThemeProvider;
constructor(props) {
super(props);
}
render() {
return (
<Header>
<Left>
<Button transparent>
<Icon name='add' size={Layout.navIconSize} />
</Button>
</Left>
<Body>
<Title>Header</Title>
</Body>
<Right>
<Button transparent>
<Icon name='alarm' size={Layout.navIconSize} />
</Button>
</Right>
</Header>
)
}
}
export default NavBar;
Themes
export const LightTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'rgb(242, 242, 242)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)',
notification: 'rgb(255, 69, 58)',
}
}
export const DarkTheme = {
dark: true,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'rgb(0, 0, 0)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)',
notification: 'rgb(255, 69, 58)',
},
};
You have done the major part, you just have to do some minor changes to get it to work.
First In order to change the values of a context you will have to export the context. Then access the consumer.
import React from "react";
import { LightTheme, DarkTheme } from '../themes'
export const Context = React.createContext();
export class ThemeProvider extends React.Component {
state = {
theme: LightTheme,
updateTheme: (theme) => {
this.setState({ theme: theme })
}
}
render() {
const { theme } = this.state
return (
<Context.Provider value={this.state} theme={theme} >
{ this.props.children }
</Context.Provider>
)
}
}
export default ThemeProvider;
In the child component which is the NavBar in your case, you will have to import it and use the consumer to do updates Import the context like below (Your actual paths may vary)
import ThemeProvider, { Context } from './ThemeProvider';
class NavBar extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Context.Consumer>
{({ theme, updateTheme }) => (
<Header>
<Left>
<Button
title="Update Theme"
onPress={() => updateTheme(theme.dark ? LightTheme : DarkTheme)}
/>
<Button transparent>
<Icon name="add" size={Layout.navIconSize} />
</Button>
</Left>
<Body>
<Title>Header</Title>
</Body>
<Right>
<Button transparent>
<Icon name="alarm" size={Layout.navIconSize} />
</Button>
</Right>
</Header>
)}
</Context.Consumer>
);
}
}
{({ theme, updateTheme }) => ( The above line provides access to your theme value in the context and updateTheme. You can try out the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With