react-native-dark-mode
⚠️ DEPRECATED ⚠️
Please upgrade to React Native 0.62 and react-native-dynamic (in 1.0.0 all high level APIs are available, intentionally undocumented, will be removed in 2.0.0).
Installation
Prevent Android app from restarting when dark mode changes
You must append |uiMode
to the android:configChanges
prop of <activity>
in AndroidManifest.xml
. Example:
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -13,7 +13,7 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
UIUserInterfaceStyle
in Info.plist
(iOS) Make sure you don't have In iOS you can force the operating system to display your app always in light mode or dark mode by specifying it in Info.plist
. If you did that in the past this module will not work.
React Native 0.60 or above
npm install react-native-dark-mode
cd ios && pod install # for iOS
React Native 0.59
npm install react-native-dark-mode
react-native link react-native-dark-mode
Usage
High level APIs
useDarkMode
Returns a boolean. true
when dark mode is on.
import { useDarkMode } from 'react-native-dark-mode'
function Component() {
const isDarkMode = useDarkMode()
return <View style={{ backgroundColor: isDarkMode ? 'black' : 'white' }} />
}
useDarkModeContext
Returns dark
or light
.
import { useDarkModeContext } from 'react-native-dark-mode'
const backgroundColors = {
light: 'white',
dark: 'black',
}
function Component() {
const mode = useDarkModeContext()
const backgroundColor = backgroundColors[mode]
return <View style={{ backgroundColor }} />
}
DynamicStyleSheet
, DynamicValue
and useDynamicStyleSheet
Just like StyleSheet
but with support for dynamic values.
import { DynamicStyleSheet, DynamicValue, useDynamicStyleSheet } from 'react-native-dark-mode'
const dynamicStyles = new DynamicStyleSheet({
container: {
backgroundColor: new DynamicValue('white', 'black'),
flex: 1,
},
text: {
color: new DynamicValue('black', 'white'),
textAlign: 'center',
},
})
function Component() {
const styles = useDynamicStyleSheet(dynamicStyles)
return (
<View style={styles.container}>
<Text style={styles.text}>My text</Text>
</View>
)
}
DarkModeProvider
Allows you to set a specific mode for children.
import { DarkModeProvider } from 'react-native-dark-mode'
function MyScreen() {
return (
<>
{/* will be rendered using dark theme */}
<DarkModeProvider mode="dark">
<Component />
</DarkModeProvider>
{/* will be rendered using light theme */}
<DarkModeProvider mode="light">
<Component />
</DarkModeProvider>
{/* will be rendered using current theme */}
<Component />
</>
)
}
It is recommended to wrap your application in a DarkModeProvider
without a mode
prop to observe a performance improvement.
function App() {
return (
<DarkModeProvider>
{/* ... */}
</DarkModeProvider>
)
}
useDynamicValue
Returns the appropriate value depending on the theme. You can either pass a DynamicValue
or just two arguments.
import { DynamicValue, useDynamicValue } from 'react-native-dark-mode'
const lightLogo = require('./light.png')
const darkLogo = require('./dark.png')
const logoUri = new DynamicValue(lightLogo, darkLogo)
function Logo() {
const source = useDynamicValue(logoUri)
return <Image source={source} />
}
import { useDynamicValue } from 'react-native-dark-mode'
function Input() {
const placeholderColor = useDynamicValue('black', 'white')
return <TextInput placeholderTextColor={placeholderColor} />
}
Low level APIs
initialMode
This is the initial mode that the app started in.
import { initialMode } from 'react-native-dark-mode'
console.log('App started in', initialMode, 'mode')
eventEmitter
Allows you to subscribe to changes in the mode.
import { eventEmitter } from 'react-native-dark-mode'
eventEmitter.on('currentModeChanged', newMode => {
console.log('Switched to', newMode, 'mode')
})
Requirements
iOS
- Xcode 11
- React Native 0.59.9 or higher
- iOS 13 to see it in action
Android
- Android 10 or Android Auto to see it in action