Dark Mode not working React Navigation React Native - react-native

I Am working on this to implement Dark Mode in React Native using React Navigation. but it changes only the bottom bar navigator not the screens inside that. can you help me with this
Snack Code
https://snack.expo.io/#belgin/news-app

You're responsible for styling inside your own components. You're styling background as light, setting navigation theme to dark is not gonna magically change the colors you have defined.
For changing themes to work for your components, you need to use the useTheme hook to set colors in your own components instead of hardcoding them.
import * as React from 'react';
import { TouchableOpacity, Text } from 'react-native';
import { useTheme } from '#react-navigation/native';
function MyScreen() {
const { colors } = useTheme();
return (
<View style={{ flex: 1, backgroundColor: colors.background }}>
{/* screen content */}
</View>
);
}
https://reactnavigation.org/docs/themes/#using-the-current-theme-in-your-own-components

Other method is that, you can also create a state which can store your current view-mode (light/dark mode). This is very simple to implement using react-redux. You can refer this video to get better understanding of react and redux.
This is far more simpler implementation of redux.
Note - dependencies such as thunk, react-redux, etc etc are not installed in this video. You can identify which dependencies you're gonna need step-by-step by following error that came in your way. Eg. if createStore gives error try to import createStore as legacy_createstore like done in this question

Related

How can I toggle a dark theme for a stack of screens?

I have included a snack expo here that reproduces the exact layout of my project. App.js -> stack of screens. I am trying to figure out the best way to toggle between light theme and dark theme. I do not care for the ios dark theme setting to trigger this, for now, I just want the button to trigger it.
I would like there to be a button displayed on my home screen that when pushed toggles to the theme it is not currently on. I originally wanted to use theme provider to set my colors for each theme and then call that color on each page rather than the hard coded color but have failed to do so.
When you have a stack of screens being called in a tab navigator, what is the best way to use a dark theme?
You need to use the theme prop of the NavigationContainer but your are still responsible for providing the styling for each of your components.
That said, there are a couple of things we need to do here.
Let the button change the theme prop of the NavigationContainer.
Provide a custom styling (colors etc.) for all of your components depending of the theme.
We can solve the first problem by wrapping the NavigationContainer into a ContextProvider as follows.
import React, {useState} from 'react';
import {
DefaultTheme,
DarkTheme,
NavigationContainer,
} from '#react-navigation/native';
export const ThemeContext = React.createContext();
export default function App() {
const [theme, setTheme] = useState(DefaultTheme)
return (
<ThemeContext.Provider value={{theme, setTheme}}>
<NavigationContainer theme={theme}>
</NavigationContainer>
</ThemeContext.Provider>
);
}
In your Toggle component you can then change the theme dynamically as follows.
import {ThemeContext} from '../App'
import {
DefaultTheme,
DarkTheme,
} from '#react-navigation/native';
const Toggle = (props) => {
const { setTheme, theme } = React.useContext(ThemeContext);
return (
<TouchableOpacity onPress={() => setTheme(theme === DefaultTheme ? DarkTheme : DefaultTheme)}>
</TouchableOpacity>
);
}
You will notice that changing the theme will not change anything in your current setup. This is because you need to take care of this yourself.
This could be done using either the context again or the useTheme hook. For your HomeScreen this could be done as follows.
import { useTheme } from '#react-navigation/native';
const Home = () => {
const { colors } = useTheme();
return (
<View style={{justifyContent: 'center', alignItems: 'center', flex: 1, backgroundColor: colors.background}}>
<Toggle/>
<Screen/>
</View>
);
}
Toggling the button changes the theme now. You can access the default theme colors using the useTheme hook but you still need to apply it to your components. You could also provide a custom theme which is done similar.
I would suggest doing something similar to this:
https://www.section.io/engineering-education/how-to-control-dark-mode-in-react-native-using-redux/.
In the article the author uses React Native Paper to control what each of his screens look like. I personally have a theme.js file that has an if statement based on what my Redux state is set to. If it is to light mode, my global theme variables (e.g. background color, text color, etc.) are set to their respective light colors. When set to dark mode, my global theme variables are set to their respective dark colors.

React Native Mapbox GL: MarkerView component is missing

I hope this is the right place to ask. I'm developing a react-native-mapbox-gl/maps app on Windows 10, and the MarkerView component just isn't showing up. Here's the App.js code for reference:
import React, { Component } from 'react';
import {
StyleSheet,
} from 'react-native';
import MapboxGL from '#react-native-mapbox-gl/maps';
MapboxGL.setAccessToken('MY_TOKEN')
export default function App() {
return (
<MapboxGL.MapView
style={{ flex: 1, width: '100%' }}
styleURL={MapboxGL.StyleURL.Street}
showUserLocation={true}>
</MapboxGL.MapView>
);
};
The MapView component and other MapboxGL components are working properly, yet whenever I try to invoke the MapboxGL.MarkerView component (be it inside of Mapview or in any other place in the App), the program does not recognize it. Going to the #react-native-mapbox-gl/maps module yields no results either, as the MarkerView class is missing. Has it been deprecated and the GitHub docs not updated? Is there a replacement?
Thanks in advance.
Notes:
RN Version: 0.62.2;
react-native-mapbox-gl/maps version: 8.1.0 (master).
The Mapbox Token has been properly installed and used;
There are no installation issues either on the client or server sides of the app.
you can use MapboxGL.PointAnnotation component instead
Or you can user 8.0.0 version

Do i have to make seperate MyComponent.android.js file to use SafeArea

I am pretty new to react-native. Whenever i have to make use of SafeAreaView I have to make a seperate .android.js file for same component without safe area leading to duplication.
Is it possible to conditionally use SafeAreaView with platform.os?
Yes, It is possible to use SafeAreaView with Conditionally for Platform.OS.
SafeAreaView only applicable on ios, but also work on android.
On my code SafeAreaView work on both OS.
If there is a need only on a particular OS then give condition.
I have same problem. So what I done is that create one component called whatever you want eg. SafeScrollView.js and then render conditionally SafeAreaView in that component then pass children to that component.
For example :
I have SafeScrollView.js like below :
import React from 'react';
import { View, SafeAreaView, Platform } from 'react-native';
const SafeScrollView = (props) => {
if (Platform.OS === "ios") {
return (
<View style={props.style}>
{props.children}
</View>
);
}
return (
<SafeAreaView style={props.style}>
{props.children}
</SafeAreaView>
)
}
export default SafeScrollView
Then use SafeScrollView as a component like below :
<SafeScrollView>
// Your component
</SafeScrollView>
Now, In IOS it will render normal View component and if device is android it will render SafeScrollView.
So, you don't have to create separate file.
SafeAreaView only supports ios. So, you can use conditional statement to you this for particular os.

React native form design

I want to create in form in react native which has material input text.
same like shown here https://material.angular.io/components/input/overview
Here is my code
import React, { Component } from "react";
import { Platform, StyleSheet, Text, View, TextInput } from "react-
native";
export default class App extends Component<Props> {
render() {
return <TextInput style={styles.abcd} placeholder="Enter name" />;
}
}
const styles = StyleSheet.create({
abcd: {
borderBottomWidth: 0.25,
marginVertical: 2,
paddingHorizontal: 10
}
});
Here, I have used a placeholder, but if you see the form in the given link, then it's not placeholder. Also, the text is moving in an upward direction, when we are clicking on the field. The same thing I want to achieve here.
I don't want to use any libraries like textField or any other library.
The placeholder prop on TextInput components has the place-holding text disappear upon the start of input. To achieve what you want to do, you can overlay a Text component over your TextInput component and map its style to a state variable. Upon focus, change the Text component's styling accordingly.
Buddy,
There are two things
1. React-Native material input box is only available in Android by default.
2. On iOS, (iPhone or iPad) you will see normal InputBox
To see the material input box on iOS devices, you have to do lots of coding. The best solution is to integrate third-party libraries like react-native-paper
Please refer a working example over here with react-native-paper library
https://github.com/callstack/react-native-paper/blob/master/example/src/TextInputExample.js

StatusBar backgroundColor removed after pressing back button (android)

I'm using the StatusBar component in react native (Android). Here is an example code from my App.js component:
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import { RootNavigator } from './components/Router';
export default class MainApp extends Component {
render() {
return (
<View style={{flex: 1}}>
<StatusBar backgroundColor='black' barStyle="light-content"/>
<RootNavigator />
</View>
);
}
}
The StatusBar is working properly when you launch the app, when you navigate through the entire app and when put in background and then return.
It's NOT working when exiting the app by pressing back button. When you launch the app again, the statusbar backgroundColor is suddenly grey (default color).
Is this a known bug or something? I can't figure out how to fix this.
Alright, shortly after submitting the question I found out about another strategy, using imperative API. I avoided it at first since according to official documentation:
For cases where using a component is not ideal, there
is also an imperative API exposed as static functions on the
component. It is however not recommended to use the static API and the
component for the same prop because any value set by the static API
will get overriden by the one set by the component in the next render.
Here is my revised code:
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import { RootNavigator } from './components/Router';
export default class MainApp extends Component {
componentWillMount() {
StatusBar.setBackgroundColor('black');
}
render() {
return (
<View style={{flex: 1}}>
<StatusBar backgroundColor='black' barStyle="light-content"/>
<RootNavigator />
</View>
);
}
}
It seems like this works properly now. When I press the back button and launch the app again the statusbar remains black. I won't declare this as the correct answer just yet in case someone has an explanation why this happens or a better solution.
Edit: This also appears to work only 90% of the time or so. I've noticed, once in a while, when pressing back button and returning the statusbar remained grey. It is absolutely boggling at this point, I suppose componentWillMount isn't always triggered?
Edit2: After switching to componentDidMount instead of componentWillMount as suggested, it seems to be working 100% of the time now.