最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - react-native-appearance not listening to change event for First Time - Stack Overflow

programmeradmin2浏览0评论

I am trying a setup , So that when I change my System theme my react native app theme should also change. I have use react navigation and react-native-appearance. On app startup correct system theme is applied, But when I change theme while using app for first time it doesn't. But When I try to change system theme for second time it also changes app theme and works correctly.

here is my code :-

App.js

import React from 'react';
import {} from 'react-native';
import {AppearanceProvider} from 'react-native-appearance';
import Main from './main';

export default function App() {
  
  return (
    <AppearanceProvider>
        <Main/>
    </AppearanceProvider>
  );
}

Main.js

import React, { useState,useEffect } from 'react';
import {} from 'react-native';
import {Appearance} from 'react-native-appearance';
import {DarkTheme,DefaultTheme,NavigationContainer} from '@react-navigation/native';
import Home from './home';

const myDarkTheme={
    ...DarkTheme,
    colors:{
        ...DarkTheme.colors,    
        text:"#fff",
        statusBarColor:"#000"
    }
  };
  
  const myLightTheme={
    ...DefaultTheme,
    colors:{
        ...DefaultTheme.colors,
        text:"#000",
        statusBarColor:"rgb(242, 242, 242)"
    }
  };



export default function Main(){
    const [theme,setTheme]=useState();
    console.log(theme);
    
   const onThemeChange=()=>{
        const newColor=Appearance.getColorScheme();
        setTheme(newColor);
    }

    useEffect(()=>{
        onThemeChange()

        const subscription=Appearance.addChangeListener(()=>{
            onThemeChange()
        })

        return ()=>subscription.remove();
    },[])

    return(
        <NavigationContainer theme={theme === 'light' ? myLightTheme : myDarkTheme}>
            <Home/>
        </NavigationContainer>
    )
}

And Home.js

import React from 'react';
import { StyleSheet, Text, View,StatusBar } from 'react-native';
import {useTheme} from '@react-navigation/native';

export default function Home(){
    const {colors}=useTheme();
    return (
      <View style={{...styles.container,backgroundColor:colors.background}}>
        <Text style={{color:colors.text}}>Open up App.js to start working on your app!</Text>
        <StatusBar barStyle={colors.statusBarColor==='#000' ? 'light-content':'dark-content'} backgroundColor={colors.background}/>
      </View>
    );
}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
    },
  });

Please help me So that theme Changes for first time also when I change system theme for first time after app startup.

I am trying a setup , So that when I change my System theme my react native app theme should also change. I have use react navigation and react-native-appearance. On app startup correct system theme is applied, But when I change theme while using app for first time it doesn't. But When I try to change system theme for second time it also changes app theme and works correctly.

here is my code :-

App.js

import React from 'react';
import {} from 'react-native';
import {AppearanceProvider} from 'react-native-appearance';
import Main from './main';

export default function App() {
  
  return (
    <AppearanceProvider>
        <Main/>
    </AppearanceProvider>
  );
}

Main.js

import React, { useState,useEffect } from 'react';
import {} from 'react-native';
import {Appearance} from 'react-native-appearance';
import {DarkTheme,DefaultTheme,NavigationContainer} from '@react-navigation/native';
import Home from './home';

const myDarkTheme={
    ...DarkTheme,
    colors:{
        ...DarkTheme.colors,    
        text:"#fff",
        statusBarColor:"#000"
    }
  };
  
  const myLightTheme={
    ...DefaultTheme,
    colors:{
        ...DefaultTheme.colors,
        text:"#000",
        statusBarColor:"rgb(242, 242, 242)"
    }
  };



export default function Main(){
    const [theme,setTheme]=useState();
    console.log(theme);
    
   const onThemeChange=()=>{
        const newColor=Appearance.getColorScheme();
        setTheme(newColor);
    }

    useEffect(()=>{
        onThemeChange()

        const subscription=Appearance.addChangeListener(()=>{
            onThemeChange()
        })

        return ()=>subscription.remove();
    },[])

    return(
        <NavigationContainer theme={theme === 'light' ? myLightTheme : myDarkTheme}>
            <Home/>
        </NavigationContainer>
    )
}

And Home.js

import React from 'react';
import { StyleSheet, Text, View,StatusBar } from 'react-native';
import {useTheme} from '@react-navigation/native';

export default function Home(){
    const {colors}=useTheme();
    return (
      <View style={{...styles.container,backgroundColor:colors.background}}>
        <Text style={{color:colors.text}}>Open up App.js to start working on your app!</Text>
        <StatusBar barStyle={colors.statusBarColor==='#000' ? 'light-content':'dark-content'} backgroundColor={colors.background}/>
      </View>
    );
}

const styles = StyleSheet.create({
    container: {
      flex: 1,
      alignItems: 'center',
      justifyContent: 'center',
    },
  });

Please help me So that theme Changes for first time also when I change system theme for first time after app startup.

Share Improve this question asked Aug 4, 2020 at 9:10 NamanNaman 801 silver badge9 bronze badges 1
  • Have you found a solution? – Paul Commented Nov 30, 2020 at 12:42
Add a ment  | 

5 Answers 5

Reset to default 6

modify the MainActivity.java

import android.content.res.Configuration; // <--- import

// copy these lines
@Override
public void onConfigurationChanged(Configuration newConfig) {
  super.onConfigurationChanged(newConfig);
  getReactInstanceManager().onConfigurationChanged(this, newConfig);
}

According to the docs Appearence.addChangeListener, is provided with the callback function which has colorScheme. You can use that to update the state directly, no need to call the onThemeChange() function again.

useEffect(()=>{
    onThemeChange();

    const subscription = Appearance.addChangeListener(({ colorScheme }) => {
        setTheme(colorScheme);
    })

    return () => subscription.remove();
},[])

There's an open issue,

https://github./facebook/react-native/issues/28823

If you are using react-native then you can merge in the branch someone has provided on the above issue to fix it. But I am using Expo.

It's worthwile to mention that, in case you are using a chrome based debugger the theme always will be light. Either disable debugging or switch the debugger.

https://github./facebook/react-native/issues/28823#issuement-640671784

I was having the same problem with the hook only returning 'light', no matter how much I'd toggle the appearance in the simulator.

After a lot of digging into code, it turned out the reason it was doing this was due to - the debugger! If you're using a Chrome-based debugger (either in browser or using the standalone RN debugger) the Appearance module will always return light, due to the debugger not being able to handle async functions (or something like that, it was a few days ago!).

I can't say I understand the idiosyncracies as to why it does this, but the upshot of it all is I stopped using the Chrome debugger and moved to flipper - and it worked! I'm now able to swap between dark and light mode using the useColorTheme hook as expected.

Hope this helps someone else, it was a head scratcher for me for quite a while!

For class ponent

import React from "react";

    import {
      SafeAreaView,
      Text,
      View,
      Dimensions,
      StyleSheet,
      TouchableHighlight,
      Image,
      ImageBackground,
      TextInput,
      TouchableOpacity,
      ScrollView,
      KeyboardAvoidingView,
      FlatList,
      Appearance,
      Animated,
    } from "react-native";

constructor(props) {
    super(props);
    this.state = {
      theme: false,
    };
  }

      ponentDidMount() {
        Appearance.getColorScheme() == "dark"
          ? this.setState({ theme: true })
          : this.setState({ theme: false })
     
      }
    
    
      ponentDidUpdate() {
        this.subscription=Appearance.addChangeListener((theme) => {
          // console.log("theme", theme);
          theme.colorScheme == "dark"
            ? this.setState({ theme: true })
            : this.setState({ theme: false });
        });
      }
      ponentWillUnmount() {
        this.subscription.remove();
      }

    render() {
    return (
      <View
        style={[
          {
            padding: 1,
            flex: 1,
          },
          { backgroundColor: this.state.theme == true ? "#000" : "#fff" },
        ]}
  

    >
    )}

For functional ponent

    const [theme, setTheme] = useState(false);
     useEffect(() => {
        themeCheck();
      }, []);
    
      const themeCheck = async () => {
        const getScheme = await Appearance.getColorScheme();
        getScheme == "dark" ? setTheme(true) : setTheme(false);
      };
      useEffect(() => {
        const subscription = Appearance.addChangeListener((theme) => {
          // console.log("theme", theme);
          theme.colorScheme == "dark" ? setTheme(true) : setTheme(false);
        });
        return () => subscription.remove();
      },[])
 return (
    <>
      {/* <StatusBar barStyle="light-content" */}
      <SafeAreaView
        style={[
          styles.containerview1,
          { backgroundColor:theme == true ? "#000" : "#fff" },
        ]}
      ></SafeAreaView></>)
发布评论

评论列表(0)

  1. 暂无评论