简体   繁体   中英

React-native dark theme in class based project

i am having trouble adding a dark-theme support to my react-native app.

theme-context.js

import React from 'react';

const themes = {
    dark: {
        backgroundColor: 'gray',
        backgroundCard: '#25282c',
        color: 'white'
    },
    light: {
        backgroundColor: 'yellow',
        backgroundCard: '#fff',
        color: 'black'
    }
}

const initialState = {
    dark: false,
    theme: themes.light,
    toggle: () => {}
}

const ThemeContext = React.createContext(initialState)

function ThemeProvider({children}) {
    const [dark, setDark] = React.useState(false) // Default theme is light

    // Toggle between dark and light modes
    const toggle = () => {
        setDark(!dark)
    }

    // Filter the styles based on the theme selected
    const theme = dark ? themes.dark : themes.light

    return(
        <ThemeContext.Provider value={{theme, dark, toggle}}>
            {children}
        </ThemeContext.Provider>
    )
}

export {ThemeProvider, ThemeContext}

App.js


 import 'react-native-gesture-handler';
 import React, { Component } from 'react';
 import {LogBox, SafeAreaView, StyleSheet, ScrollView, Button, View, Text, Image, Alert, TouchableOpacity, TouchableHighlight} from 'react-native';
 import { NavigationContainer } from '@react-navigation/native';
 import { createStackNavigator } from '@react-navigation/stack';
 import Home from './Home.js';
 import Settings from './Settings.js';
 import Icon from 'react-native-vector-icons/FontAwesome';
 import { ThemeProvider } from './theme-context'
 
 
 const Stack = createStackNavigator();
 
 function LogoTitle() {
   return (
     <Image
       style={{ width: 140, height: 50 }}
       source={require('./images/title.png')}
     />
   );
 }
 
 // ------------------App-----------------------------
 class App extends Component {
 
   render() {
     
     return (
    <ThemeProvider>
         <NavigationContainer>
           <Stack.Navigator
           screenOptions={{
             headerStyle: {
               backgroundColor: '#f4f4f4',
             },
             headerTintColor: 'gray',
             headerTitleStyle: {
               fontWeight: 'bold',
             },
           }}
         >
           <Stack.Screen
               name="Home"
               component={Home}
               options={({ navigation, route }) => ({
                 headerTitle: props => <LogoTitle {...props} />,
                 headerRight: () => (
                   <Icon.Button
                     name="cog"
                     backgroundColor="transparent"
                     size={25}
                     onPress={() => navigation.navigate('Settings')}
                     title="Settings"
                     color="gray"
                     />
                 ),
             })}
             />
             <Stack.Screen
               name="Settings"
               component={Settings}
             />
           </Stack.Navigator>
         </NavigationContainer>
    </ThemeProvider>
     );
   }
 }
 export default App;

home.js

 import 'react-native-gesture-handler';
 import React, { Component, useContext } from 'react';
 import {LogBox, SafeAreaView, StyleSheet, ScrollView, View} from 'react-native';
 import { Card } from 'react-native-elements';
 import CardOne from './Components/CardOne.js';
 import CardTwo from './Components/CardTwo.js';
 import CardThree from './Components/CardThree.js';
 import CardFour from './Components/CardFour.js';
 import { ThemeProvider } from './theme-context';

 
 
 // ------------------App-----------------------------
 class Home extends Component {
 
   constructor(props) {
       super(props);
       // ...
       }
   }
 
   render() {
     return (
      <ThemeProvider>
         <View>
           <SafeAreaView>
             <ScrollView >
                <CardOne/>
               <CardTwo/> 
               <CardThree/> 
               <CardFour /> 
             </ScrollView>
           </SafeAreaView>
         </View>
      </ThemeProvider>
     );
   }
 }
 
 
 export default Home;

next i want to useContext on one of my components for example

import React, { Component, useContext} from 'react';
import { Card } from 'react-native-elements';
import {StyleSheet, View, Text, Image, Alert, TouchableOpacity} from 'react-native';
import { ThemeContext } from 'ResCalc/theme-context';

const { dark, theme, toggle } = useContext(ThemeContext);

class CardOne extends Component {

    constructor(props) {
        super(props);
        ...
      }
    }


    render() {
        return (
            <Card containerStyle={styles.card}>
                <View>
                <Switch
                    onChange={toggle} value = {dark} />
                </View>
            </Card>
        );
    }
}


const styles = StyleSheet.create({
    card: {
        backgroundColor: theme.backgroundColor,
        borderColor: "#D1D1D6",
        borderWidth: 2, 
        borderRadius: 5,
        shadowOffset:{  width: 5,  height: 5, },
        shadowColor: '#D1D1D6',    // #D1D1D6
        shadowOpacity: 1.0,
        shadowRadius: 2,
        elevation: 3,
        
    }
  });

export default CardOne

i guess i have to use the useContext hook in a class based variant, but i just can't figure out how to do that.

hopefully someone can help me out on this:)

You can define your styles as a function and then inject your theme into it.

const styles = (theme) => StyleSheet.create({
    card: {
        backgroundColor: theme.backgroundColor,
        borderColor: "#D1D1D6",
        borderWidth: 2, 
        borderRadius: 5,
        shadowOffset:{  width: 5,  height: 5, },
        shadowColor: '#D1D1D6',    // #D1D1D6
        shadowOpacity: 1.0,
        shadowRadius: 2,
        elevation: 3,
        
    }
  });

In your component:

class CardOne extends Component {
  static contextType = ThemeContext;

  render() {
     // Pass theme context to styles functiion
     return (
            <Card containerStyle={styles(this.context.theme).card}>
                <View>
                <Switch
                    onChange={toggle} value = {dark} />
                </View>
            </Card>
        );
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM