Navigating to cart screen with stack navigation header - react-native

I am having a stack navigator that consists of 7 different screens and a cart icon is placed on the every screen header. I want to navigate by pressing that cart icon to the cart screen/page. I tried to put onPress function on the icon and in the header option also but all in vain.
Also, I want to know how the cart system will work.
Below is my single stack navigator screen
<HomeStack.Screen name="EARRINGS" component={Earring}
options={{headerRight:() => <ShoppingCartIcon /> }}
/>
Below is my ShoppingCartIcon code:
const ShoppingCartIcon = () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View style={{position: 'absolute', top: -20, right: 0, width: 70, height: 70, alignItems:"center",justifyContent:"center", zIndex:2000 }}>
<Text style={{fontSize:20,fontWeight:"bold"}}>0</Text>
</View>
<AntDesign name="shoppingcart" color="black" size={24} style={{marginRight:10}} />
</View>
)
}
export default (ShoppingCartIcon)
Please help me.

You can pass the navigation prop like below
<HomeStack.Screen
name="EARRINGS"
component={Earring}
options={({ navigation }) => ({
headerRight: () => (<ShoppingCartIcon navigation={navigation}/> )
})}
/>
And you can use the navigation prop to navigate to any screen you need
const ShoppingCartIcon = ({navigation}) => {
//other code
navigation.navigate('Cartscreen')
}

Related

React Navigation 6 - how to close modal from navigation stack

I am trying to close a React Navigation modal from the navigation stack.
Following the official React Navigation documentation navigation.goBack''' is being used within the '''Modal Screen. This successfully closes the modal, but what I would like to achieve is closing the modal by pressing a button in the navigation stack instead of in the screen.
I have tried both of the below functions and although they work as expected in the Screen, they do not work in the stack navigator.
<Button onPress={() => navigation.pop()} title="Dismiss" />
<Button onPress={() => navigation.goBack()} title="Dismiss" />
I get the following error:
undefined is not an object (evaluating 'navigation.goBack')
How can I get the modal to close by pressing a button in the stack navigator?
I think you have misunderstood this Example.
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is the home screen!</Text>
<Button
onPress={() => navigation.navigate('MyModal')}
title="Open Modal"
/>
</View>
);
}
function ModalScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>This is a modal!</Text>
<Button onPress={() => navigation.goBack()} title="Dismiss" />
</View>
);
}
const RootStack = createStackNavigator();
function RootStackScreen() {
return (
<RootStack.Navigator>
<RootStack.Group>
<RootStack.Screen name="Home" component={HomeScreen} />
</RootStack.Group>
<RootStack.Group screenOptions={{ presentation: 'modal' }}>
<RootStack.Screen name="MyModal" component={ModalScreen} />
</RootStack.Group>
</RootStack.Navigator>
);
}
Note:
both HomeScreen and ModalScreen are screen not model of any kind. screenOptions is an object where you define what type of animation you want to see when user navigate to that screen.
when you set screenOptions to model:
The modal behavior slides the screen in from the bottom and allows the
user to swipe down from the top to dismiss it on iOS.
Finally let talk about your error:
undefined is not an object (evaluating 'navigation.goBack')
navigation props will only be available on those screen which are include in your navigation.
so check that screen is present or not where your accessing navigation.goBack

TouchableOpacity inside header is affected by view with absolute position in the screen on android

I have a Viewinside a SafeAreaView in a screen which has postion:absolute. When I include the view, a TouchableOpacity rendered in the header no longer responds in ANDROID (but always works fine in iOS).
Home screen:
render() {
return (
<SafeAreaView style={styles.SafeAreaContainer}>
<View style={styles.homeBackgroundContainer}> {/* <--- offending view! */}
<BlueCircle style={styles.homeBackgroundSvg} />
</View>
<View style={styles.homeView}>
<View style={styles.homeGreetingContainer}>
<Title style={styles.homeGreeting}>Hi, </Title>
<Title style={styles.homeGreetingName}>{username}</Title>
</View>
// Other components
</View>
</SafeAreaView>
);
}
styles.homeBackgroundContainer:
homeBackgroundContainer: {
borderColor: COLOR.transparent,
position: 'absolute',
top: '-50%',
left: '-25%',
right: 0,
bottom: 0,
},
The header is declared in the drawer navigator screen options. Note the TouchableOpacity in the header - this is used to open the drawer.
works in iOS
works from the "Content" screen
works when the homeBackgroundContainer(and its children) are commented out (Home Screen)
DOES NOT WORK IN ANDROID when homeBackgroundContainer is rendered (Home Screen).
Drawer Navigation & Header:
function DrawerContainer() {
return (
<Drawer.Navigator
screenOptions={({navigation}) => ({
headerLeft: titleLogo,
headerStyle: {
// colors only
},
headerTitle: () => {},
headerRight: () => (
<TouchableOpacity
style={styles.hamburgerIconButton}
onPress={() => navigation.toggleDrawer()}>
<Image source={require('../assets/hamburger.png')} />
</TouchableOpacity>
),
})}>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
headerShown: true,
// more options
}}
/>
<Drawer.Screen
name="Content"
component={ContentScreen}
options={{
headerShown: true,
}}
/>
</Drawer.Navigator>
);
}
styles.hamburgerIconButton:
hamburgerIconButton: {
marginRight: 20,
},
Other questions on SO have shown that absolute positioning can affect TouchableOpacity. I have tried setting the zIndex of the TouchableOpacity to 1, and also tried setting a positive elevation value but there is no change in behaviour.
Visually, I can see the header colors and content is rendered on top of the view which is the desired state. So if the header is rendered over the view, why isn't the TouchableOpacity responding?
To get the TouchableOpacityin a navigation header to respond on android when there's a view on the screen which has postion: absolute, I had to bring the headerStyle(not the touchable opacity style) forward on the z-axis.
screenOptions={() => ({
headerStyle: {
zIndex: 1,
},
})};

React Native Tab Bar white space under tabs

I am using a tab bar navigator with SafeAreaView.
If I comment out the tab bar nav the parent view covers the entire screen. However when I add a Tab bar it shows a small white view under the tab bar section.
const App = () => {
return (
<SafeAreaView style={styles.droidSafeArea}>
<View style={{ backgroundColor: "red", flex: 1 }}>
<TabNavigator key="MainTabNav" />
</View>
</SafeAreaView>
);
};
export default App;
const styles = StyleSheet.create({
droidSafeArea: {
flex: 1,
backgroundColor: "#2F3438",
}
});
Try this
screenOptions={{
tabBarStyle: {
paddingBottom:0,
},
}}
Please use the tab bar outside the safeAreaView else the safe area view will calculate the notch and will render the tab bar above the notch.
2.If you are using tab bar inside the safe area view use the force inset property of safe area view : <SafeAreaView forceInset = {bottom : 'never} this will make the safeareaview collide with bottom area and your tab bar will render properly.
Note : by using this method you would have to be a bit accurate in providing the styles.
const App = () => {
return (
<SafeAreaView style={styles.droidSafeArea} forceInset = {bottom : 'never'}>
<View style={{ backgroundColor: "red", flex: 1 }}>
<TabNavigator key="MainTabNav" />
</View>
</SafeAreaView>
);
};
export default App;
const styles = StyleSheet.create({
droidSafeArea: {
flex: 1,
backgroundColor: "#2F3438",
}
});
I had the exact same issue and what I did is not use SafeAreaView at all around the tab bar, but simply assigning the color I want the white space to have as the background color for the tab bar.
In your example that would be:
return (
<View>
<TabNavigator style={{ backgroundColor: "#2F3438" }} key="MainTabNav" />
</View>
);
<NavigationContainer>
<Tab.Navigator
tabBarOptions={{
activeTintColor: Colors.tabIconSelected,
inactiveTintColor: Colors.tabIconDefault,
style: styles.container
}}/>
</NavigationContainer>
const styles = StyleSheet.create({
container: {
backgroundColor: Colors.darkBackgroundColor,
borderTopWidth: 0
}
});
Note : borderTopWidth: 0 worked for me
For react native navigation V5
<Tab.Navigator
tabBarOptions={{
style: {
borderTopWidth: 0
}
}}
>
<Tab.Screen/>
<Tab.Navigator>
Note: this is for bottom tab
When I was implementing floating button on bottomTabNavigation followed this post, I faced similar issue that tabBar has dirty white space with shadow(I used shadow in style of component).
I used React navigation v6.
issue image1, issue image2 (Sorry, It's my first Answer I post, I can't embed image yet)
I tried to remove it with borderWidth: 0, but not worked.
My case, below is worked for me.
Try this
borderRadius: 25 // some much number that near tabbar height
on
<Tab.Navigator
tabBar={(props) => (
<View style={styles.navigatorContainer}>
<BottomTabBar {...props} />
{isIphoneX() && (
<View
style={[
styles.xFillLine,
{ backgroundColor: "#fff" },
]}
/>
)}
</View>
)}
screenOptions={{
headerShown: false,
tabBarShowLabel: false,
tabBarStyle: {
borderRadius: 25, // add here
borderTopWidth: 0,
borderRadius: 25,
backgroundColor: "transparent",
elevation: 30,
},
tabBarItemStyle: { backgroundColor: "#fff" },
}}
>
...
Then result image is this.
I don't understand why It was worked, but I hope it works for someone.
I had this issue when i was using the TabBarIcon property within the Tab.Screen
Tab being const Tab = createBottomTabNavigator()
I couldn't solve the issue no matter how i used the SafeAreaView.
I solved it by not using the TabBarIcon property and instead making a custom component for the tabBar property on the higher level Tab.Navigator as outlined in the react native docs https://reactnavigation.org/docs/bottom-tab-navigator/
When i created the custom tabBar component it all worked as expected, no funky use of SafeAreaView.

How to add section divider in navigation drawer using react navigation

Suppose I have five items in drawer navigation. I want to add separator after three items. How to add this using react-navigation.
As mentioned vonovak, you could achieve this by using contentComponent which allows complete customization of drawer. For this you will need to create custom component which will override default drawer. Code sample:
Navigation Drawer
const NavigationDrawer = DrawerNavigator({
screen1: { screen: Screen1 },
screen2: { screen: Screen2 },
screen3: { screen: Screen3 },
}, {
contentComponent: SideMenu
})
Custom component which overrides default drawer (DrawerContainer)
class SideMenu extends React.Component {
render() {
return (
<View style={styles.container}>
<ScrollView>
<Text
onPress={() => this.props.navigation.navigate('Screen1')}
style={styles.item}>
Page1
</Text>
// 'separator' line
<View
style={{
borderBottomColor: 'black',
borderBottomWidth: 1
}}/>
<Text
onPress={() => this.props.navigation.navigate('Screen2')}
style={styles.item}>
Page2
</Text>
<Text
onPress={() => this.props.navigation.navigate('Screen3')}
style={styles.item}>
Page3
</Text>
</ScrollView>
</View>
);
}
}
You'll need to use the contentComponent prop to make custom changes. Check out the docs
If you are using DrawerItem component you can use itemStyle prop to add style as follows
const props = {
itemStyle: {
borderBottomWidth: 1,
borderColor: '#E2E4E8',
}
}
<DrawerItems {...props} />
You can also modify the style of container containing all items with
itemsContainerStyle prop.
Check official docs here.
3.x: https://reactnavigation.org/docs/3.x/drawer-navigator#contentoptions-for-draweritems
4.x: https://reactnavigation.org/docs/4.x/drawer-navigator#contentoptions-for-draweritems
5.x: DrawerContent is default drawer Item from v.5
You can pass props to it using drawerContentOptions object in Drawer.Navigator component.
https://reactnavigation.org/docs/5.x/drawer-navigator#drawercontentoptions
You can also pass custom drawer component using drawerContent prop.
https://reactnavigation.org/docs/5.x/drawer-navigator#drawercontent
6.x: Custom component can be added using drawerContent prop
https://reactnavigation.org/docs/drawer-navigator#drawercontent
Style to drawerItem is changed to
https://reactnavigation.org/docs/drawer-navigator#draweritemstyle
Just add this code:
const Seperator = () => <View style={styles.separator} />;
at the top of your code that you want to have the section divider/separator on. If it's a navigation drawer, menu, categories or etc.
Add this styling prop:
separator: {
marginVertical: 8,
borderBottomColor: "#737373",
borderBottomWidth: StyleSheet.hairlineWidth
}
Add section divider/separator between each section, menu, category block of code that you want to separate them like this:
//Block of code of first section/menu/category starts from here
<Icon.Button
name="th-large"
raised={true}
backgroundColor="#ffa500"
size={30}
onPress={() => {
Linking.openURL("https://www.buymeacoffee.com/splendor");
}}
>
<Text style={{ fontSize: 15 }}>
Herat: The "Academy" of Prince Bay Sunghur (1420-1433)
</Text>
</Icon.Button>
**<Seperator />**
//Block of code of first section/menu/category ends here
//Block of code of second section/menu/category starts from here
<Icon.Button
name="th-large"
raised={true}
backgroundColor="#ffa500"
size={30}
onPress={() => {
Linking.openURL("https://www.buymeacoffee.com/splendor");
}}
>
<Text style={{ fontSize: 15 }}>
Venice, Istanbul, and Herat (15th Century)
</Text>
</Icon.Button>
**<Seperator />**
//Block of code of second section/menu/category ends here
//Block of code of third section/menu/category starts from here
<Icon.Button
name="th-large"
raised={true}
backgroundColor="#ffa500"
size={30}
onPress={() => {
Linking.openURL("https://www.buymeacoffee.com/splendor");
}}
>
<Text style={{ fontSize: 15 }}>
The Age of Bihzad of Herat (1465-1535)
</Text>
</Icon.Button>
**<Seperator />**
//Block of code of thirds section/menu/category ends here

React-native-popup-menu on react-navigation header

I'm using redux with react-navigation and would like to show the popup when the user clicks on the button on the react-navigation header-right button.
I wrapped the context menu at the root of my apps, as below
return (
<Provider store={store}>
<MenuContext style={{ flex: 1 }}>
<AppWithNavigationState />
</MenuContext>
</Provider>
)
in one of my screen, I have
static navigationOptions = {
headerTitle: 'News',
headerRight: (
<TouchableOpacity style={{ paddingLeft:15, paddingRight:15 }}>
<Icon name="more-vert" size={30} color="black" />
</TouchableOpacity>
),
}
When the user clicks on the right button, it should be like this
The menu items are dynamic, I will have to pull the data from one of my API and start rendering the menu data.
I've read through online it can be achieved using the context method, but I'm not sure how to implement it in my structure.
Could anyone advise me on this?
And is it possible to render it with my local variable?
The most custom way is to use Modal, when click the right button, called this.refs.modalRef.showModal(), which in your current page:
<View>
<PopupModal ref="modalRef" />
</View>
The PopupModal like this:
export default class PopupModal extends Component {
state = {
show: false,
}
showModal() {
this.setState({show: true});
}
closeModal = () => {
this.setState({show: false});
}
return (
<Modal
transparent
visible={this.state.show}
onRequestClose={this.closeModal}
>
<TouchableWithoutFeedback onPress={this.closeModal}>
<View style={{
width: '100%',
height: '100%',
opacity: 0.5,
backgroundColor: 'gray',
}} />
</TouchableWithoutFeedback>
<View></View> // your designed view, mostly position: 'absolute'
</Modal>
);
}
You can also pass some data to PopupModal by this.refs.modalRef.showModal(data), and in PopupModal:
showModal = (data) => {
this.setState({ data, show: true });
}
https://www.npmjs.com/package/react-native-material-menu
It works to me
headerRight:<View style={{marginRight:10}}>
<Menu
ref={this.setMenuRef}
button={<Text onPress={this.showMenu}><Icon style={{color:screenProps.headerTitleStyle.color,fontSize:25,marginRight:5}} name="md-more"/></Text>}
>
<MenuItem onPress={this.hideMenu}>Rate Us</MenuItem>
<MenuItem onPress={this.hideMenu}>Share App</MenuItem>
<MenuItem onPress={this.hideMenu}>Settings</MenuItem>
</Menu>
</View>,