React Navigation / Native flickers when use custom header component - reactjs

When I change screens with react-native-navigation I have a flicker of underlying background on ios, when I change screens with standard navigation everything is going smooth but with the custom one it look like it applies background color too late, is there some prop I should be aware of when dealing with custom header bar?
this is the code of custom header:
export const CustomNavigation = (props: NativeStackHeaderProps) => {
const styles = useStyleSheet(themedStyles);
return (
<SafeAreaView style={styles.wrapper}>
<Pressable onPress={props.navigation.goBack}>
<ArrowLeftIcon />
</Pressable>
<Text>{props.options.title}</Text>
<Pressable>
<NavMenuIcon />
</Pressable>
</SafeAreaView>
);
};
const themedStyles = StyleService.create({
wrapper: {
height: Platform.OS === "ios" ? 100 : 70,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: spacing.regular,
transform: Platform.OS === "ios" ? [{ translateY: 20 }] : [],
backgroundColor: "#fff",
},
});
app.tsx
const Stack = createNativeStackNavigator<RootStackParamList>();
return (
<SafeAreaProvider onLayout={onLayoutRootView}>
<NavigationContainer>
<ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
<ReduxProvider store={store}>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
header: (props) => <CustomNavigation {...props} />,
}}
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Scheduler"
component={ScheduleScreen}
options={{
title: "Plan your booking",
}}
/>
<Stack.Screen
name="LocationPicker"
component={PickLocationScreen}
/>
</Stack.Navigator>
</ReduxProvider>
</ApplicationProvider>
</NavigationContainer>
</SafeAreaProvider>
On android it looks ok, there is no background flash, only on ios. Thanks for any suggestions.

Related

How to manage nested navigations so that Homepage displays Navbar when signed in?

I have two navigators and the idea is to have the main navigation container to hold the general pages: Home, SignIn, SignUp, confirmEmail and NewPassword but once the user login in to Home I would like the navigation bar to display and have its own navigation routings.
Navigation.js:
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
{user ? (
<Stack.Screen name="HomeScreen" component={HomeScreen} />
) : (
<>
<Stack.Screen name="SignIn" component={SignInScreen} />
<Stack.Screen name="SignUp" component={SignUpScreen} />
<Stack.Screen name="ConfirmEmail" component={ConfirmEmailScreen} />
<Stack.Screen
name="ResetPassword"
component={ResetPasswordScreen}
/>
<Stack.Screen name="NewPassword" component={NewPasswordScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
Navbar.js
const Navbar = () => {
const tabOffsetValue = useRef(new Animated.Value(0)).current;
return (
// <NavigationContainer>
<Tab.Navigator
screenOptions={{
tabBarShowLabel: false,
headerShown: false,
// Floating Tab Bar...
tabBarStyle: {
backgroundColor: 'white',
position: 'absolute',
// Max Height...
borderRadius: 10,
// Shadow...
},
}}>
{
// Tab Screens....
// Tab ICons....
}
<Tab.Screen
name={'Home'}
component={HomeScreen}
options={{
tabBarIcon: ({focused}) => (
<View
style={{
// centring Tab Button...
position: 'absolute',
top: 20,
}}>
<Icon
name="home"
size={20}
color={focused ? 'red' : 'gray'}></Icon>
</View>
),
}}
listeners={({navigation, route}) => ({
// Onpress Update....
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: 0,
useNativeDriver: true,
}).start();
},
})}>
</Tab.Screen>
HomeScreen.Js
const HomeScreen = () => {
const signOut = () => {
Auth.signOut();
};
return (
<View>
<Navbar/>
<Text style={{fontSize: 24, alignSelf: 'center'}}>Welcome to Flimpi</Text>
<Text
onPress={signOut}
style={{
width: '100%',
textAlign: 'center',
color: 'red',
marginTop: 'auto',
marginVertical: 20,
fontSize: 20
}}>
Sign Out!
</Text>
</View>
);
};
Expectedly I am getting the following error:
Require cycle: src/screens/HomeScreen/index.js -> src/components/Navbar/index.js -> src/components/Navbar/Navbar.js -> src/screens/HomeScreen/index.js
Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
The Error makes sense but I just do not know how to structure the code

Strange Shadow in TabBar Styles

please somebody help me, does anybody know about this strange shadow box in my tab bar? i cant change and its driving me crazy:
So this is my code:
const Tab = createBottomTabNavigator();
export default () => (
<Tab.Navigator
tabBar={props => <CustomTabBar2 {...props} />}
screenOptions={({route}) => ({
headerShown: false,
tabBarShowLabel: true,
tabBarInactiveTintColor: Colors.dark,
tabBarStyle: styles.tabBarStyle,
tabBarActiveTintColor: Colors.primary,
tabBarIcon: ({color, size, focused}) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'ios-home-sharp' : 'ios-home-outline';
} else if (route.name === 'Sequences') {
iconName = focused ? 'settings' : 'settings-outline';
} else if (route.name === 'Animals') {
iconName = focused ? 'wallet' : 'wallet-outline';
} else if (route.name === 'Plants') {
iconName = focused
? 'md-notifications-sharp'
: 'md-notifications-outline';
}
return <Icon name={iconName} size={32} color={color} />;
},
})}>
<Tab.Screen
name="Home"
component={MainStack}
options={{headerShown: false}}
/>
<Tab.Screen
name="Sequences"
component={SequencesStack}
options={{headerShown: false}}
/>
<Tab.Screen name="Animals" component={Animals} />
<Tab.Screen name="Plants" component={Plants} />
</Tab.Navigator>
);
const styles = StyleSheet.create({
tabBarStyle: {
position: 'absolute',
backgroundColor: Colors.transparent,
},
});
and this is the props that im passing to my tab bar
const CustomTabBar = props => {
return (
<View>
<View style={styles.tabBar} />
<BottomTabBar {...props} />
</View>
);
};
export default CustomTabBar;
const styles = StyleSheet.create({
tabBar: {
position: 'absolute',
right: 0,
left: 0,
bottom: 0,
height: 90,
backgroundColor: Colors.white,
borderTopLeftRadius: 35,
borderTopRightRadius: 35,
alignContent: 'center',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
},
});
I tried to change everything in both sides but i cannot find the styles thats making this shadow between my tabbar, is something wrong or anybody has like a example to show me? Thanks so much

Navigate to another screen - 'navigation.navigate' is not a function

I am trying to navigate from Screen1 to Screen2. Screen1 is being rendered in my Home screen. So far I have tried using this.props.navigation.navigate as well as what you see currently implemented.
I have created a snack expo here that recreates the exact error as well as posted some code below.
Thank you for any insight at all, I appreciate it more than you know.
EDIT:: this needs to be ran on IOS and I am using react-native-navigation
App.js
/*passing props to home is from my overall project, I left it in incase it impacted the answer*/
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="HomeScreen" options={{ headerShown: false }}>
{(props) => (
<Home {...props}/>
)}
</Stack.Screen>
<Stack.Screen
name="Screen1"
component={Screen1}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen2"
component={Screen2}
options={{ headerShown: false }}
/>
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyTabs/>
</NavigationContainer>
);
Screen1
export default class Screen1 extends React.Component {
renderList = (props, navigation) => {
return List.map((item, i) => {
return (
<View
key={List.name}
style={{
width: windowWidth,
height: scale(100),
paddingLeft: scale(10)
}}>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Screen2')}
activeOpacity={0.7}>
<Text style={{fontSize: 20}}>{item.name}</Text>
</TouchableOpacity>
</View>
);
});
};
render() {
return (
<View style={{top: scale(50)}}>
<ScrollView style={{ height: windowHeight }}>
<this.renderList />
</ScrollView>
</View>
);
}
}
make use of hook useNavigation.
Home.js
const Home = (props) => {
const navigation = useNavigation();
return (
<View>
<Screen1 navigation={navigation} />
</View>
);
};
Screen1.js
export default class Screen2 extends React.Component {
renderList = (props) => {
return List.map((item, i) => {
return (
<View
key={List.name}
style={{
width: windowWidth,
height: scale(100),
paddingLeft: scale(10),
}}>
<TouchableOpacity onPress={() => {
props.navigation.navigate('Screen2')
}} activeOpacity={0.7}>
<Text style={{ fontSize: 20 }}>{item.name}</Text>
</TouchableOpacity>
</View>
);
});
};
render() {
const props= this.props;
return (
<View style={{ top: scale(50) }}>
<ScrollView style={{ height: windowHeight }}>
{ this.renderList (props) }
</ScrollView>
</View>
);
}
}
snack expo working code
In Screen 1
renderList = (props) => {
return List.map((item, i) => {
return (
<View
key={List.name}
style={{
width: windowWidth,
height: scale(100),
paddingLeft: scale(10)
}}>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Screen2')}
activeOpacity={0.7}>
<Text style={{fontSize: 20}}>{item.name}</Text>
</TouchableOpacity>
</View>
);
});
in Home
const Home = (props) => {
return (
<View>
<Screen1 {...props}/>
</View>
);
}
And in App
<Tab.Navigator initialRouteName="Home">
<Tab.Screen name="Home" options={{ headerShown: false }} component={Home}/>
<Tab.Screen
name="Screen1"
component={Screen1}
options={{ headerShown: false }}
/>
<Tab.Screen
name="Screen2"
component={Screen2}
options={{ headerShown: false }}
/>
</Tab.Navigator>
And for me working perfectly (I take some capture but I'm not authorized yet, new user...)
Say me
You are not passing navigation props to Screen1. You can just pass navigation props to Screen1 like below code or it is better to make Screen1 as Initial Route instead of calling it as a component in Home screen.
Good method : Update following area in App.js like below
....
<Stack.Navigator initialRouteName="Screen1"> // made Screen1 as initial route
<Stack.Screen
name="Screen1"
component={Screen1}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Screen2"
component={Screen2}
options={{ headerShown: false }}
/>
</Stack.Navigator>
....
Method 2 : If you want Home Screen as Initial Route, then update following area in Home.js like below
....
const Home = (props) => {
return (
<View>
<Screen1 navigation={props.navigation}/> // navigation props passed to Screen1 component
</View>
);
}
....

React Native Bottom tab bar jump on every load

i have the exact same problem like on issue:
React Native header / bottom tabbar jumping on first app load
On every load the bottom bar jumps up and down for unknown reason. I wrapped the root app in SafeAreaProvider, i wrapped my screens in SafeAreaView and still the same thing happens.
Here is my code:
Root App:
const App = () => {
return (
<SafeAreaProvider>
<StatusBar backgroundColor="#01497C" />
<NavigationContainer>
<Stack.Navigator
initialRouteName="AuthLoadingScreen"
screenOptions={{headerShown: false}}>
<Stack.Screen
name="AuthLoadingScreen"
component={AuthLoadingScreen}
/>
<Stack.Screen name="Home" component={Tabs} />
<Stack.Screen name="QuizScreen" component={QuizScreen} />
<Stack.Screen name="QuizReviewScreen" component={QuizReviewScreen} />
<Stack.Screen name="QuizEndScreen" component={QuizEndScreen} />
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
};
Tabs:
const Tabs = () => {
const TabBarCustom = ({children, onPress}) => {
return (
<TouchableOpacity
style={{top: -10, justifyContent: 'center', alignItems: 'center'}}
onPress={onPress}
activeOpacity={1}>
<LinearGradient
style={{
width: 70,
height: 70,
borderRadius: 35,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
}}
colors={['#01497C', '#89C2D9']}>
{children}
</LinearGradient>
</TouchableOpacity>
);
};
return (
<Tab.Navigator
tabBarOptions={{
showLabel: false,
style: {
height: 60,
},
}}>
<Tab.Screen
name="Quizzes"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="apps-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Quizzes
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Flashcards"
component={FlashCardsScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="copy-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Flashcards
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Import"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Icon
name="plus"
color={focused ? '#A9D6E5' : 'white'}
size={42}
/>
</View>
),
tabBarButton: props => <TabBarCustom {...props} />,
}}
/>
<Tab.Screen
name="Account"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="person-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Account
</Text>
</View>
),
}}
/>
<Tab.Screen
name="About"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="search"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Search
</Text>
</View>
),
}}
/>
</Tab.Navigator>
);
};
The issue happens every time tabs get loaded.
I had the same issue, in my case I was using Custom StatusBar in different screens with different props. The issue was I wasn't using translucent prop in all screen StatusBar. Using translucent in all screen StatusBar fixed the problem. Give me a thumbs up if it solve your problem.
I use MaterialCommunityIcons for tab icons so,
I sove this issue with
useLayoutEffect(() => {
async function loadIcons() {
setIsLoading(true);
await MaterialCommunityIcons.loadFont();
setIsLoading(false);
}
loadIcons();
}, []);
if (isLoading) {
return <></>;
}
Why useLayouEffect?
The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint. read more

React Native Navigation Custom Border

I am a beginner in React Native. I want to configure the React Navigation 5.x with custom style. And I am unable to trim border-bottom like following. Please help me with This.
Custom Style for React Navigation
My Current Code:
function StackNavigator() {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerStyle: styles.header,
headerBackImage: () => (
<Image
style={styles.headerBack}
source={require("../assets/icons/64x/chevron-left.png")}
/>
),
headerLeftContainerStyle: {
alignItems: "flex-start",
paddingHorizontal: theme.sizes.padding / 2
},
headerTitleStyle: styles.headerTitle
}}
>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: true }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
header: {
height: theme.sizes.base * 5,
backgroundColor: Colors.white,
borderWidth: 0,
elevation: 0,
borderBottomWidth: 1,
borderBottomColor: Colors.grayLight
},
headerBack: {
height: 20,
width: 20
},
headerTitle: {
fontSize: 18,
fontFamily: "Quicksand",
letterSpacing: -1
}
});
Thank you in advance.
You can add this style to the cardStyle property of the screenOptions:
function StackNavigator() {
<NavigationContainer>
<Stack.Navigator
screenOptions={{
cardStyle : { backgroundColor : 'lightgray', margin : 15 },
headerStyle: styles.header,
headerBackImage: () => (
<Image
style={styles.headerBack}
source={require("../assets/icons/64x/chevron-left.png")}
/>
),
headerLeftContainerStyle: {
alignItems: "flex-start",
paddingHorizontal: theme.sizes.padding / 2
},
headerTitleStyle: styles.headerTitle
}}
>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: true }}
/>
</Stack.Navigator>
</NavigationContainer>
}
Which will produce something like this:

Resources