Reputation: 119
I know useContext is not specifically for components due to functionality, but I am trying to use ThemeContext and I know there is a way around it here. I saw the documentation for it where they use a class component but still could not make much sense of it.
I have included a snack example here where classComponent.js is what I want to implement. I would like it to render the same as Friends.js but using a class component rather than a function. In this same snack, I would like toggle.js to be a class component.
This is the code I am trying to replicate.
const Toggle = (props) => {
const { setTheme, theme } = React.useContext(ThemeContext);
return (
<TouchableOpacity onPress={() => setTheme(theme === DefaultTheme ? DarkTheme : DefaultTheme)}>
and this is the code that I have that I am trying to implement the above code in.
export default class Toggle extends React.Component {
//How can I set my state?
state = {}
render(){
return(
<TouchableOpacity onPress={() => setTheme(theme === DefaultTheme ? DarkTheme : DefaultTheme)}>
);
}
Upvotes: 1
Views: 1694
Reputation: 9836
First, we convert toggle.js
to a class component
. There are two things that we need to do and one of them is not obvious at all (and I do not know why this is necessary, but there is an old bug on GitHub which has no satisfying answer yet).
ThemeContext
to its own file (I don't know why this is necessary; maybe because the export must be a default export
?).static contextType = ThemeContext
Thus, the following converts toggle.js
to a class component.
ThemeContext.js
import React from 'react'
const ThemeContext = React.createContext();
export default ThemeContext
toggle.js
import ThemeContext from '../ThemeContext'
class Toggle extends React.Component {
static contextType = ThemeContext
constructor(props) {
super(props)
}
render() {
const {theme, setTheme} = this.context
return <TouchableOpacity onPress={() => setTheme(theme === Light ? Dark : Light)}>
<View style={{ height: 50, width: 100, backgroundColor: 'blue', justifyContent:'center', alignItems: 'center' }}>
<Text style={{color: 'white',fontSize: 20 }}>Toggle theme</Text>
</View>
</TouchableOpacity>
}
}
export default Toggle;
Using the useTheme
hook in a class component is not possible for obvious reasons. There is no alternative for class components.
The official way to solve this problem is to wrap the class component into a functional component and pass the theme
from useTheme
as a prop to the class component. This is recommended in the documentation.
I have renamed it to Friends.js
.
import { useTheme } from '@react-navigation/native';
class Friends extends React.Component {
render() {
const { theme } = this.props;
return (
/* I would like to be able to call colors.primary and colors.secondary here rather than green and grey */
<View style={{justifyContent: 'center', alignItems: 'center', flex: 1, backgroundColor: theme.colors.primary}}>
<View style={{ height: 100, width: 300, backgroundColor: theme.colors.secondary, justifyContent:'center', alignItems: 'center' }}>
<Text style={{color: "black",fontSize: 30 }}>Friends Screen</Text>
</View>
</View>
);
}
}
// Wrap and export
export default function(props) {
const theme = useTheme();
return <ClassComponent {...props} theme={theme} />;
}
Here is an updated snack using class components.
Upvotes: 4