How to change default background colour in React Native - react-native

I recently updated from RN 0.60 to 0.65, and after hours of debugging I can get my app to build and run again. However, for some reason the background colour of my app has changed from white to gray.
I'm using react-native-router-flux for navigation, but either the styling is broken in the latest react-native release, or I'm missing something obvious.
Here's how it has always been set up:
const RouterComponent = () => {
const sceneConfig = {
cardStyle: {
backgroundColor: 'white',
},
};
return (
<Router {...sceneConfig}/>
[...]
</Router>
This no longer does anything. Here's what else I've tried:
Directly adding style properties to <Router> using sceneStyle, as recommended in the docs
Directly adding style properties to each individual scene by using style property
Neither of these approaches work, and I'm now stuck with an app that has a gray background (#f2f2f2) on every screen. I'm not even sure if this is an issue with react-native-router-flux but it definitely seems like the most likely cause.
Digging through the issues on the Github repo, I found one person flagging that this could be an incompatibility with react-native-screens, which seems to have been added to my project as a result of the upgrade to RN 0.65. This is a shot in the dark, as I'm not even sure what that library is used for.
Has anyone managed to change the background colour of their app on RN 0.65 and react-native-router-flux v4.3.0?
Edit:
Here's an example of how I tried to style individual scenes, which didn't work:
<Scene
title={'Profile'}
renderTitle={() => <View />}
// Neither of the below options has any effect
sceneStyle={{backgroundColor: 'red'}}
style={{backgroundColor: 'red'}}
key="profile"
hideNavBar
icon={TabIcon}
iconName="account-circle-outline"
back={false}
component={Profile}
/>

I suggest you create a wrapper component and wrap your pages on it to easily manage the specification.
this is the way I use it in my applications:
const MainView = ({children}) => {
return (
<View style={styles.container}>{children}</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ff0",
},
});
Now, use this component in other screens, for example in the HomeScreen:
const HomeScreen = () => {
// rest of the codes ...
return (
<MainView>
// rest of the codes ...
</MainView>
)
}
You can even pass the container style through props to the MainView instead of creating the style on it. in this way, you can pass different styles in different screens.

Related

Not getting the height of the status bar when using custom drawer header

I am stuck kind of. I wanted to create a customer head for my drawer. Was planning to do something similar to what we see with Reddit. The problem I am running into are two different ones.
1 - If I try to add a <SafeAreaView /> I get a lot of padding/margin to the bottom. I will attach an image to the bottom to show what I mean.
2 - If I don't use the wrapper then we have the statusbar overlapping the team (also will attach the image). I am not seeing any mention about the status bar height within the properties given.
If anyone has a better approach for the problem I am having, I am open to hear any advice. My main goal is to have a custom head.
Will provide the code as well for this block of code
<Drawer.Screen
name="testingit"
component={TabNav}
options={{
header: (props) => {
console.log(props);
const open = () => {
console.log("opening");
props.navigation.openDrawer();
};
return (
<View
style={{
backgroundColor: "yellow",
margin: 0,
padding: 0,
}}
>
<Text onPress={open}>Hellow</Text>
</View>
);
},
}}
/>
It looks like I found the solution a few minutes after posting.
export const CustomSafeAreaView = (props: any) =>
<SafeAreaView edges={['top', 'left', 'right']}>{props.children}</SafeAreaView>
This also goes to create toward the person who mention this solution here https://github.com/th3rdwave/react-native-safe-area-context/issues/167#issuecomment-758264492

React native navigation stack navigator header not fixed at top for web

This very basic app with a single stack navigator doesn't behave as expected for web. On iOS/Android the header stays in place and the screen scrolls under the header. For web the header doesn't stay fixed on top. See this snack https://snack.expo.io/#tositsa/nested-stacks-fixed-header-issue-2
I think this might be a bug in react-native-navigation or react-native-web, but I'd love to see if there is a workaround somehow.
I ran into a similar problem when trying to render a custom header component with React Navigation 5 on Expo React Native for Web. I was able to resolve the problem by setting the positioning to 'fixed' just for the web like this. This should work for using custom header components, but I'm not sure if you could apply the same solution for the default header component.
In the stack/screen configuration
// ...
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
header: () => <MyCustomHeader />
}}
/>
In the Custom Header Component to be rendered by RN5
// ...
const MyCustomHeader = ({ title }) => {
return (
<View style={styles.headerContainer}>
<Text>{title}</Text>
</View>
);
}
const styles = {
headerContainer: {
...Platform.select({
web: {
position: "fixed"
}
}),
height: 60,
width: '100%',
}
}
Found a better solution in the end (the way RNN designed it):
cardStyle: { flex: 1 } in screenOptions
does the trick as well.

React Native Flex Child Growth Seemingly Affected by Padding

I am experiencing some difficulty when using flex for layout in React Native. I have reduced the behaviour I am experiencing down the the following problem.
I have one container which fills the available space since it has flex set to 1. I then have a child within that container which should fill the container, so I have set it's flex to 1. I also want the container to have padding at the top. I would therefore expect the child to fill all of the parent apart from the top 20%. However, what I am seeing is that there is equal padding at the top and bottom of the container around the child (as if I had set paddingVertical instead of paddingTop).
Is anyone able to explain why this behaves as it does? I am also intrigued by the behavior I saw when creating a snack to illustrate this problem. On the iOS and Android simulators I am experiencing the behaviour which seems erroneous to me whereas the Web view seems to work as I would expect with only a gap at the top.
Thanks!
Snack example code
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default function App() {
return (
<View style={styles.container}>
<View style={styles.child}>
<Text>
Change code in the editor and watch it change on your phone! Save to get a shareable url.
</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'green',
paddingTop: '20%'
},
child: {
flex:1,
backgroundColor:'red'
},
});
Android - 'broken' behaviour
Web - 'expected' behaviour

React Navigation custom navigator transitions

I'm looking to create a Stack Navigator that can handle animating specific elements between 2 screens. Fluid Transitions looked like a library I could use, but it doesn't support react-navigation 5.X. If there's a package that has this functionality for react-navigation v5, that would be great.
However, if there is no current package for v5, I'd like to extend the StackNavigator to handle this kind of functionality. I've been able to remove the default animations for the StackNavigator with something similar to the following (where transition is a bool taken in the options prop for the Stack.Screen:
const CustomTransitionStackNavigator = ({
initialRouteName,
children,
screenOptions,
...rest
}) => {
if (descriptors[state.routes[state.index].key].options.transition) {
return (
<View style={{ flex: 1 }}>
{descriptors[state.routes[state.index].key].render()}
</View>
);
}
return (
<StackView
{...rest}
descriptors={descriptors}
navigation={navigation}
state={state}
/>
);
};
I'd like to be able to use a Context (or some other method) of passing the transition progress to the scene's descendants in order to handle the animations. Is there some way to get the transition progress in v5? Or would this CustomTransitionStackNavigator need to manage that state? Thanks!
You can use CardAnimationContext or useCardAnimation (which is just a convenience wrapper for the first one) to get transition progress in a stack navigator.
For example:
import { useCardAnimation } from '#react-navigation/stack';
import React from 'react';
import { Animated } from 'react-native';
export const SomeScreen = () => {
const { current } = useCardAnimation();
return (
<Animated.View
style={{
width: 200,
height: 200,
backgroundColor: 'red',
transform: [{ scale: current.progress }],
}}
/>
);
};
This feature seems to be undocumented at the moment, but you can check TypeScript definitions to get some more information.

How to show View within styled (using styled-components) View - React Native

I am learning React Native and styled components. I am working on a simple iOS app and facing some problems with styled-components.
What I'm trying to do
I am trying to show modal on click which looks like this
<Modal visible={this.state.isModalVisible} animationType={'fade'}>
<StyledView flex={1} padding={10} backgroundColor={'orange'}>
<View>
...more Views and Texts
</View>
</StyledView>
</Modal>
StyledView is a custom view that I have created using styled-components which looks like this
const ViewWrapper = styled.View`
flex: ${props => props.flex};
padding: ${props => props.padding};
backgroundColor: ${props => props.backgroundColor};
`;
const StyledView = ({ flex, padding, backgroundColor }) => (
<ViewWrapper
flex={flex}
padding={padding}
backgroundColor={backgroundColor}
/>
);
export default StyledView;
Problems I'm having
1) When I set padding={10}, I get an error Failed to parse declaration "padding: 10".
2) After Googling a bit, I found that I should be using padding={'10px'} which throws this error, 10px is of type NSString cannot be converted to YGValue. Did you forget the % or pt suffix?.
(padding={'10%'} works fine)
Then I simply tried setting flex and padding values in ViewWrapper and send only background color as prop.
3) But for some reason, Views and Texts nested within StyledView does not show up.
Please tell me why it's not working and help me understand what I'm missing here. Thanks.
You have a couple of issues.
Styled Components do not accept strings in them, so you cannot
sent the '10px' from the prop.
You are correct that padding
needs a px at the end. Something padding alone does not work, but
you can workaround it by adding paddingVertical and
paddingHorizontal with the same value which is the same as padding.
You are overcomplicating the implementation as you dont need to
pass the style props and you can define them all within your styled
component. Like this:
import styled from "styled-components/native"
const StyledView = styled.View`
flex: 1;
padding: 10px;
backgroundColor: orange
`;
And then you just use it like this:
<Modal visible={this.state.isModalVisible} animationType={'fade'}>
<StyledView>
<View>
...more Views and Texts
</View>
</StyledView>
</Modal>
No need for the ViewWrapper or more props. Also, and this is just personal. I only use StyledComponents for the ones that could change at run time or depend on a theme, like exts for fontFamily or fontSize. For the rest that have constant styles that never change, I just use normal styles objects since it is less verbose.
If this is a simplified version and you absolutely need the props you con move them all into one single theme object and pass it with a ThemeProvider and then just read it as ${props.theme.backgroundColor} or something.
Cheers