I'm a beginner programmer and I'm trying to created a nested navigator in react native. The stack navigator on the Home screen works but the stack navigator on the MyEvents Screen does not. I use the tabs to navigate between Home and MyEvents and within the those pages I want to use a stack navigator to get to other pages. Please help! (also please let me know if I am being unclear)
This is Router.js
import React from 'react';
import {StackNavigator, TabNavigator} from 'react-navigation';
import InputScreen from './InputPage';
import HomeScreen from './Home';
import DetailsScreen from './Details';
import MyEventsScreen from './MyEvents';
import EditScreen from './EditPage';
import MapScreen from './Map';
const BottomNavigation = require('react-native-bottom-navigation');
export const Tabs = TabNavigator({
Home: {screen: HomeScreen},
EventMap: {screen: MapScreen},
Input: {screen: InputScreen},
MyEvents:{screen: MyEventsScreen},
},{
tabBarOptions: {
activeTintColors: '#e91e63',
//swipeEnabled: true,
}
});
export const EventsStack = StackNavigator({
Home: {
screen: Tabs,
},
Details: {
screen: DetailsScreen,
navigationOptions: {
header: null,
},
},
});
export const MyEventsStack = StackNavigator({
MyEvents: {
screen: Tabs,
navigationOptions: {
header: null
}
},
MyEventsDetails: {
screen: EditScreen,
navigationOptions: {
header: null,
/*navigation: ({ navigation }) => ({
title: `${navigation.state.params.name.first.toUpperCase()} ${navigation.state.params.name.last.toUpperCase()}`,
}),*/
},
},
});
export const Root = StackNavigator({
TabNav: {
screen: EventsStack,
}
}, {headerMode: 'none'});
This is Home.js
import React, {Component} from 'react';
import {View, Text, TouchableHighlight, SectionList} from 'react-native';
import {ListItem} from 'react-native-elements';
import {firebaseApp} from './App';
import Icon from 'react-native-vector-icons/MaterialIcons';
import {StackNavigator, TabNavigator} from 'react-navigation';
import {Tabs} from './Router';
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
this.itemsRef = firebaseApp.database().ref().child('items');
console.ignoredYellowBox = [
'Setting a timer'
];
}
onLearnMore = (item) => {
this.props.navigation.navigate('Details', {
...item
});
};
static navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({tintColor}) => (
<Icon
name = {'Home'}
size = {26}
style = {{color: tintColor}} />
)
}
listenForItems(itemsRef) {
itemsRef.on('value', (snap) => {
// get children as an array
var items = [];
snap.forEach((parent) => {
var children = [];
parent.forEach((child) => {
children.push({
"name": child.val().name,
"when": child.val().when,
"who": child.val().who,
});
});
items.push({
data: children,
key: parent.key.toUpperCase(),
})
});
this.setState({
data: items
});
});
}
componentDidMount() {
this.listenForItems(this.itemsRef);
}
render() {
var styles = require('./Styles');
const {navigate} = this.props.navigation;
return (
<View style={{flex: 1}}>
<View style={styles.header}>
<Text style={styles.title}>Princeton Events</Text>
</View>
<View style={styles.body}>
<SectionList renderItem={({item}) => <ListItem style={styles.item}
title={item.name} subtitle={item.when}
onPress={() => this.onLearnMore(item)}/>}
renderSectionHeader={({section}) =>
<Text style={styles.sectionHeader}>{section.key}</Text>}
sections={this.state.data} keyExtractor={(item) => item.name}/>
</View>
</View>
);
}
}
This is MyEvents.js
import React, {Component} from 'react';
import {View, Text, TouchableHighlight, FlatList} from 'react-native';
import {ListItem, List} from 'react-native-elements';
import Icon from 'react-native-vector-icons/MaterialIcons';
import Router from './Router';
export default class MyEventsScreen extends Component {
onViewMyEvent = (item) => {
this.props.navigation.navigate('Edit', {
...item
});
};
static navigationOptions = {
tabBarLabel: 'MyEvents',
tabBarIcon: ({tintColor}) => (
<Icon
name = {'account circle'}
size = {26}
style = {{color: tintColor}} />
)
}
render() {
var styles = require('./Styles');
const {navigate} = this.props.navigation;
return (
<View style={{
flex: 1
}}>
<View style={styles.header}>
<Text style={styles.title}>My Events</Text>
</View>
<View style={styles.body}>
<List containerStyle={{
borderTopWidth: 0,
borderBottomWidth: 0
}}>
<FlatList data={[
{
"name": "Event 1",
"who": "E-Club",
"what": "description goes here description goes here description goes here",
"when": "1:00",
"where": "Ehub",
"RSVP": "yes"
}, {
"name": "Event 2",
"who": "Club 2",
"what": "description goes here",
"when": "2:00",
"where": "Location 2",
"RSVP": "no"
}
]} renderItem={({item}) => <ListItem style={styles.item} title={item.name} subtitle={item.when} containerStyle={{
borderBottomWidth: 0
}} onPress={() => this.onViewMyEvent(item)}/>} keyExtractor={(item, index) => index}/>
</List>
</View>
<View style={styles.footer}>
<TouchableHighlight style={styles.button} onPress={() => navigate('Home')} underlayColor='#ffd199'>
<Text style={styles.buttonText}>Back</Text>
</TouchableHighlight>
</View>
</View>
);
}
}
Related
Would anyone be able to give me help regarding React Navigation with Expo? The issue is with the drawer component where the 'Hamburger' icon isn't opening or closing the component when a user presses the icon. However, it does open/close on a default swipe gesture from React Navigation. Please see below for my code:
Router:
import React from 'react';
import { NavigationContainer, DrawerActions } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { IconButton } from 'react-native-paper'
import i18n from '../i18n/i18n';
//Theme
import Theme from '../theme/theme'
//Components
import Menu from '../components/Menu'
//Import Interfaces
import { RootDrawerParamList } from '../utils/typescript/type.d';
import { IProps } from '../utils/typescript/props.d';
//Import Screens
import Screen1 from '../screens/Screen1';
import Screen2 from '../screens/Screen2';
import SettingsScreen from '../screens/Settings';
const Drawer = createDrawerNavigator<RootDrawerParamList>();
export default class Router extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
}
render() {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName='Screen1'
drawerContent={(props: any) => <Menu {...props} />}
screenOptions={({
swipeEnabled: true
})}>
<Drawer.Screen
name="Screen1"
component={Screen1}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
headerRight: () => (<IconButton icon="cog" size={24} color={Theme.colors.text} onPress={() => navigation.navigate('Settings')} />),
route: {route},
navigation: {navigation}
})}
/>
<Drawer.Screen
name="Settings"
component={SettingsScreen}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
headerTitle: i18n.t('settings', 'Settings'),
headerLeft: () => (<IconButton icon="arrow-left" color={Theme.colors.text} size={24} onPress={() => navigation.goBack()} />),
route: {route},
navigation: {navigation}
})}
/>
<Drawer.Screen
name="Screen2"
component={Screen2}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
route: {route},
navigation: {navigation}
})}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
}
Menu
import React from 'react';
import { FlatList, StyleSheet, View } from 'react-native';
import { List, Title } from 'react-native-paper';
import { getDefaultHeaderHeight } from '#react-navigation/elements';
import { DrawerItem } from '#react-navigation/drawer';
import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context';
//Import Interfaces
import { IListItem } from '../utils/typescript/types.d';
import { IPropsMenu } from '../utils/typescript/props.d';
import { IStateMenu } from '../utils/typescript/state.d';
//A function is used to pass the header height, using hooks.
function withHeightHook(Component: any){
return function WrappedComponent(props: IPropsMenu) {
/*
Returns the frame of the nearest provider. This can be used as an alternative to the Dimensions module.
*/
const frame = useSafeAreaFrame();
/*
Returns the safe area insets of the nearest provider. This allows manipulating the inset values from JavaScript. Note that insets are not updated synchronously so it might cause a slight delay for example when rotating the screen.
*/
const insets = useSafeAreaInsets();
return <Component {...props} headerHeight={getDefaultHeaderHeight(frame, false, insets.top)} />
}
}
class Menu extends React.Component<IPropsMenu, IStateMenu> {
constructor(props: IPropsMenu) {
super(props);
this.state = {
menu: [
{
name: 'screen1.name',
fallbackName: 'Screen 1',
icon: 'dice-multiple-outline',
iconFocused: 'dice-multiple',
onPress: this.props.navigation.navigate.bind(this, 'screen1')
},
{
name: 'screen2.name',
fallbackName: 'Screen 2',
icon: 'drama-masks',
iconFocused: 'drama-masks',
onPress: this.props.navigation.navigate.bind(this, 'screen2')
}
]
}
}
renderItem = (item : IListItem) => {
const { i18n } = this.props.state.routes[0].params;
return (
<DrawerItem
label={ i18n.t(item.name, item.fallbackName) }
onPress={ item.onPress ? item.onPress: () => {} }
icon={ ({ focused, color, size }) => <List.Icon color={color} style={[styles.icon, {width: size, height: size }]} icon={(focused ? item.iconFocused : item.icon) || ''} /> }
/>
);
};
render() {
const { headerHeight } = this.props;
const { menu } = this.state;
const { Theme } = this.props.state.routes[0].params;
return (
<View>
<View style={{
backgroundColor: Theme.colors.primary,
height: headerHeight ?? 0,
}}>
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
}}>
<View style={{
flexDirection: 'row',
alignItems: 'center',
marginBottom: 5,
marginLeft: 5
}}>
<Title style={{ color: Theme.colors.text, marginLeft: 5 }}>
Title
</Title>
</View>
</View>
</View>
<FlatList
data={menu}
keyExtractor={item => item.name}
renderItem={({item}) => this.renderItem(item)}
/>
</View>
);
};
}
export default withHeightHook(Menu);
const styles = StyleSheet.create({
icon: {
alignSelf: 'center',
margin: 0,
padding: 0,
height:20
},
logo: {
width: 24,
height: 24,
marginHorizontal: 8,
alignSelf: 'center'
},
});
The solution to my issue was to encapsulate the drawer component in a native stack component. The 'Hamburger' icon works as expected, thanks for all the help and suggestions.
// Import Screens
import DrawRouter from './DrawRouter';
const Stack = createNativeStackNavigator<RootStackParamList>();
export default (): React.ReactElement => {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Main" component={DrawRouter} />
</Stack.Navigator>
</NavigationContainer>
);
};
Add the toogleDrawer() method to your onPress event on your Drawer.Navigator component:
onPress={()=> navigation.toggleDrawer()
I tried to make the simplest possible shared element transition with text but it didn't work at all. The text does not move smoothly at all. I read the documentation and followed the steps but no luck. So my code so far -
App.js
import {NavigationContainer} from '#react-navigation/native';
import * as React from 'react';
import {createSharedElementStackNavigator} from 'react-navigation-shared-element';
import DetailScreen from './DetailScreen';
import ListScreen from './ListScreen';
const Stack = createSharedElementStackNavigator();
const App = ({navigation}) => {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="List"
screenOptions={{
headerShown: false,
}}>
<Stack.Screen name="MainScreen" component={ListScreen} />
<Stack.Screen
name="DetailScreen"
component={DetailScreen}
options={navigation => ({
headerBackTitleVisible: false,
cardStyleInterpolator: ({current: {progress}}) => {
return {
cardStyle: {
opacity: progress,
},
};
},
})}
sharedElements={route => {
const {data} = route.params;
console.log(data);
return [
{
id: `item.${data.id}`,
animation: 'move',
resize: 'stretch ',
align: 'center-top',
},
];
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
ListScreen.js -
import * as React from 'react';
import {Text, TouchableOpacity, View} from 'react-native';
import {SharedElement} from 'react-native-shared-element';
const ListScreen = props => {
const {navigation} = props;
const persons = [
{
id: '1',
name: 'Earnest Green',
},
{
id: '2',
name: 'Winston Orn',
},
{
id: '3',
name: 'Carlton Collins',
},
{
id: '4',
name: 'Malcolm Labadie',
},
{
id: '5',
name: 'Michelle Dare',
},
];
return (
<View
style={{
flex: 1,
padding: 50,
}}>
{persons.map(person => {
return (
<TouchableOpacity
onPress={() => navigation.navigate('DetailScreen', {data: person})}>
<SharedElement id={`item.${person.id}`}>
<Text style={{padding: 20, fontSize: 15, marginTop: 5}}>
{person.name}
</Text>
</SharedElement>
</TouchableOpacity>
);
})}
</View>
);
};
export default ListScreen;
And DetailScreen.js -
import * as React from 'react';
import {Text, View} from 'react-native';
import {SharedElement} from 'react-navigation-shared-element';
const DetailScreen = ({route}) => {
const {data} = route.params;
return (
<View style={{flex: 1, justifyContent: 'flex-start', alignItems: 'center'}}>
<SharedElement id={`item.${data.id}`}>
<Text style={{fontSize: 22}}>{data.name}</Text>
</SharedElement>
</View>
);
};
export default DetailScreen;
So my transition now look like
it is not smooth at all. How can i fix that?
Sorry for my bad English!
You are importing the SharedElement from react-native-shared-element.
You should import it from react-navigation-shared-element
Hello guys so I wanted to add a navigation DRAWER inside my main screen and I did not know how to nest it with the already existing stack navigator ,
this is my navigation component :
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons,Item } from "react-navigation-header-buttons";
import HeaderButton from '../components/UI/HeaderButton'
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
const RootNavigation=()=> {
const Stack = createStackNavigator();
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
const screenOptions ={
headerShown:true,
headerStyle: {
backgroundColor: 'white',},
headerTintColor: 'aqua',
headerTitleStyle: {
fontWeight: 'bold',
},
};
return(
<NavigationContainer>
<Stack.Navigator initialRouteName='ProductsOverview' screenOptions={screenOptions}>
<Stack.Screen name='ProductsOverview' component={ProductsOverviewScreen} options={({navigation,route})=>({title:'All Products',headerTitleStyle:{fontFamily:'open-sans-bold'},
headerRight:()=>( <HeaderButtons HeaderButtonComponent={HeaderButton}><Item title ='Cart' iconName='md-cart' onPress={()=>{navigation.navigate('CartScreen')}}/></HeaderButtons>)})}/>
<Stack.Screen name='ProductsDetail' component={ProductDetails} options={({route})=>({title:route.params.productTitle,headerTitleStyle:{fontFamily:'open-sans-bold'}})} />
<Stack.Screen name='CartScreen' component={CartScreen} options={{title:'Cart Items', headerTitleStyle:{fontFamily:'open-sans-bold'}}} />
<Stack.Screen name='OrdersScreen' component={OrdersScreen} options={{title:'Orders '}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default RootNavigation;
and this is my app.js
import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import {createStore , combineReducers} from 'redux';
import { Provider} from 'react-redux';
import AppLoading from 'expo-app-loading';
import * as Font from 'expo-font';
import productsReducer from './store/reducers/products';
import {composeWithDevTools} from 'redux-devtools-extension'
import RootNavigation from './navigation/ShopNavigation';
import cartReducer from './store/reducers/cart'
import { useState } from 'react';
import ordersReducer from './store/reducers/orders'
const rootReducer=combineReducers({
products: productsReducer,
cart: cartReducer,
orders:ordersReducer,
});
const store = createStore(rootReducer,composeWithDevTools());
const fetchFonts=()=>{
return Font.loadAsync({
'open-sans': require('./assets/fonts/OpenSans-Regular.ttf'),
'open-sans-bold': require('./assets/fonts/OpenSans-Bold.ttf')
})
}
export default function App() {
const [fontLoaded,setfontLoaded]= useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={()=>setfontLoaded(true)}
onError={console.warn}
/>
);
}
return (
<Provider store={store}>
<RootNavigation />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
can you give me an idea how to nest them together I tried using the docs but still full of errors
and Thanks
Drawer Navigator must be a parent to both Stack and Tab navigators. With that knowledge, let we refactor our code as below:
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/UI/HeaderButton";
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
import { createDrawerNavigator } from "#react-navigation/drawer";
const RootNavigation = () => {
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const AppStack = () => (
<Stack.Navigator
initialRouteName="ProductsOverview"
screenOptions={screenOptions}
>
<Stack.Screen
name="ProductsOverview"
component={ProductsOverviewScreen}
options={({ navigation, route }) => ({
title: "All Products",
headerTitleStyle: { fontFamily: "open-sans-bold" },
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title="Cart"
iconName="md-cart"
onPress={() => {
navigation.navigate("CartScreen");
}}
/>
</HeaderButtons>
),
})}
/>
<Stack.Screen
name="ProductsDetail"
component={ProductDetails}
options={({ route }) => ({
title: route.params.productTitle,
headerTitleStyle: { fontFamily: "open-sans-bold" },
})}
/>
<Stack.Screen
name="CartScreen"
component={CartScreen}
options={{
title: "Cart Items",
headerTitleStyle: { fontFamily: "open-sans-bold" },
}}
/>
<Stack.Screen
name="OrdersScreen"
component={OrdersScreen}
options={{ title: "Orders " }}
/>
</Stack.Navigator>
);
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="MainStack" component={AppStack} />
</Drawer.Navigator>
</NavigationContainer>
);
};
export default RootNavigation;
I omitted component code below as can't access drawer.
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
Here a minified version of working implementation
https://snack.expo.dev/#emmbyiringiro/69dc5b
I have implemented a StackNavigator and a DrawerNavigator, in my DrawerNavigator in the first option I am calling StackNavigator. The problem is that when I'm browsing Stack screens I wanted to go back to the main screen through Drawer but this doesn't happen because Stack stores the last screen the user was on.
I have tried using some Navigation Prop but I am not sure where to insert this code or even which of the commands to use on the stack.
MenuDrawer.js
import React from 'react';
import {
View,
ScrollView,
Text,
StyleSheet,
TouchableOpacity,
Image,
Dimensions
} from 'react-native';
export default class MenuDrawer extends React.Component{
navLink(nav, text) {
return(
<TouchableOpacity style={{height: 50}} onPress={() => this.props.navigation.navigate(nav)}>
<Text style={styles.link}>{text}</Text>
</TouchableOpacity>
)
}
render() {
return(
<ScrollView styles={styles.continer}>
<View style={styles.topImage}>
<Image style={styles.image} source={require('../images/informationappscreen/act.png')} />
</View>
<View style={styles.bottomLinks}>
{this.navLink('Principal', 'Principal')}
{this.navLink('Sobre o Aplicativo', 'Sobre o Aplicativo')}
{this.navLink('Sobre os Responsáveis', 'Sobre os Responsáveis')}
{this.navLink('Sobre o Projeto', 'Sobre o Projeto')}
{this.navLink('Política e Termos', 'Política e Termos')}
</View>
<View style={styles.footer}>
<Text style={styles.description}>ACT</Text>
<Text style={styles.version}>v1.3.0</Text>
</View>
</ScrollView>
);
}
}
App.js
import React from 'react';
import { View, Dimensions } from 'react-native';
import { Button, Icon } from 'native-base';
import { createAppContainer, createStackNavigator, createDrawerNavigator } from 'react-navigation';
...
const HomeNavigator = createStackNavigator ({
'Main1': {
screen: Main1,
navigationOptions: {
title: 'Menu Principal',
headerRight: (<View></View>)
}
},
'Main2': {
screen: Main2,
navigationOptions: {
title: 'Menu Principal',
headerRight: (<View></View>)
},
},
'SecondMain': {
screen: SecondMain,
navigationOptions: {
title: 'Menu Querer'
}
},
'Action1': {
screen: Action1,
navigationOptions: {
title: 'Ações'
}
},
...
}, {
defaultNavigationOptions: ({ navigation }) => {
return {
headerTitleStyle: {
fontWeight: 'bold'
},
headerLeft: (
<Button transparent onPress={() => navigation.toggleDrawer()}>
<Icon name='menu' style={{color: '#FFF'}} />
</Button>
),
headerRight: (
<HomeIcon navigation={navigation} />
),
headerStyle: {
backgroundColor: '#b80003'
},
headerTintColor: '#FFF'
}
}
});
const DrawerConfig = {
drawerWidth: Dimensions.get('window').width * 0.75,
contentComponent: ({ navigation }) => {
return(<MenuDrawer navigation={navigation} />)
}
}
const DrawerNavigator = createDrawerNavigator (
{
'Principal': {
screen: HomeNavigator
},
'Sobre o Aplicativo': {
screen: InformationApp
},
'Sobre os Responsáveis': {
screen: Team
},
'Sobre o Projeto': {
screen: Project
},
'Política e Termos': {
screen: Policy
}
},
DrawerConfig
);
const AppDrawerContainer = createAppContainer(DrawerNavigator);
export default AppDrawerContainer;
Can you try reset , change method navLink
import { StackActions, NavigationActions } from 'react-navigation';
navLink(nav, text) {
return (
<TouchableOpacity
style={{ height: 50 }}
onPress={() => {
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: nav })]
});
this.props.navigation.dispatch(resetAction);
}}
>
<Text style={styles.link}>{text}</Text>
</TouchableOpacity>
);
}
Try using this.props.navigation.push('your_pagename') this will push new item to the stack. It means when using push componentDidMount() method call again
I am building an application with React Native and React Navigation, I have made all the settings and it is working, however, when the drawer is fired the image is updated multiple times causing spikes and failures to trigger buttons contained in it.
e.g.:
I am using:
react: 16.8.3,
react-native: 0.59.1,
react-native-ui-kitten: ^3.1.2,
react-navigation: ^3.4.0
I was using version 3 of RN and to try to solve I went back to version 2 but without success.
I put some warnings in the method that executes the image and saw that it is called whenever there is this update.
I already changed the image in different sizes and formats but it also did not help.
I already tested on cell phones and emulators but with no success.
Drawer:
import React, { Component } from 'react';
import {
TouchableHighlight,
View,
ScrollView,
Image,
Platform,
StyleSheet,
} from 'react-native';
import {
RkStyleSheet,
RkText,
RkTheme,
} from 'react-native-ui-kitten';
import Icon from 'react-native-vector-icons/Ionicons';
import Routes from '../../config/navigation/routes';
import logo from '../../assets/smallLogo.png';
export default function SideNavigation(props) {
const onMenuItemPressed = item => {
props.navigation.navigate(item.id);
};
const renderIcon = () => (<Image style={styles.image} source={logo}/>);
const renderMenuItem = item => (
<TouchableHighlight style={styles.container} key={item.id} underlayColor={RkTheme.current.colors.button.underlay} activeOpacity={1} onPress={() => onMenuItemPressed(item)}>
<View style={styles.content}>
<View style={styles.content}>
<RkText style={styles.icon} rkType='moon primary xlarge'><Icon name={item.icon} size={25}/></RkText>
<RkText rkType='regular'>{item.title}</RkText>
</View>
{/*<RkText rkType='awesome secondaryColor small'>{FontAwesome.chevronRight}</RkText>*/}
</View>
</TouchableHighlight>
);
const renderMenu = () => Routes.map(renderMenuItem);
return (
<View style={styles.root}>
<ScrollView showsVerticalScrollIndicator={false}>
<View style={[styles.container, styles.content]}>
{renderIcon()}
</View>
{renderMenu()}
</ScrollView>
</View>
)
}
const styles = RkStyleSheet.create(theme => ({
container: {
height: 60,
paddingHorizontal: 16,
borderTopWidth: StyleSheet.hairlineWidth,
borderColor: theme.colors.border.base,
},
root: {
paddingTop: Platform.OS === 'ios' ? 20 : 0,
backgroundColor: theme.colors.screen.base
},
content: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
icon: {
marginRight: 13,
},
image:{
resizeMode: 'contain',
maxWidth: 125
}
}));
Drawer setup:
import React, {Component} from 'react';
import { View, Text} from 'react-native';
import Login from './screens/login';
import PasswordRecovery from './screens/passwordRecovery';
import Home from './screens/home';
import SideNavigator from './components/sideMenu';
import { bootstrap } from './config/bootstrap';
import {
createDrawerNavigator,
createStackNavigator,
createAppContainer
} from 'react-navigation';
import { withRkTheme } from 'react-native-ui-kitten';
import NavBar from './components/navBar';
import AppRoutes from './config/navigation/routesBuilder';
import Splash from './screens/splash';
bootstrap();
const renderHeader = (navigation, props) => {
const ThemedNavigationBar = withRkTheme(NavBar);
return (
<ThemedNavigationBar navigation={navigation} headerProps={props} />
);
};
const App = createStackNavigator({
Splash: Splash,
Login: Login,
PasswordRecovery: PasswordRecovery,
Main: createDrawerNavigator({
...AppRoutes
},{
contentComponent: props => {
const SideNav = withRkTheme(SideNavigator);
return <SideNav {...props}/>
}
}),
},
{
headerMode: 'none',
})
export default createAppContainer(App);
Routes setup:
import React from 'react';
import _ from 'lodash';
import { createStackNavigator } from 'react-navigation';
import { withRkTheme } from 'react-native-ui-kitten';
import transition from './transitions';
import Routes from './routes';
import NavBar from '../../components/navBar';
const main = {};
const flatRoutes = {};
const routeMapping = (route) => ({
screen: withRkTheme(route.screen),
title: route.title,
});
(Routes).forEach(route => {
flatRoutes[route.id] = routeMapping(route);
main[route.id] = routeMapping(route);
route.children.forEach(nestedRoute => {
flatRoutes[nestedRoute.id] = routeMapping(nestedRoute);
});
});
const renderHeader = (navigation, props) => {
const ThemedNavigationBar = withRkTheme(NavBar);
return (
<ThemedNavigationBar navigation={navigation} headerProps={props} />
);
};
const DrawerRoutes = Object.keys(main).reduce((routes, name) => {
const rawRoutes = routes;
rawRoutes[name] = {
name,
screen: createStackNavigator(flatRoutes, {
initialRouteName: name,
headerMode: 'screen',
cardStyle: { backgroundColor: 'transparent' },
transitionConfig: transition,
defaultNavigationOptions: ({ navigation }) => ({
gesturesEnabled: false,
header: (props) => renderHeader(navigation, props),
}),
}),
};
return rawRoutes;
}, {});
const AppRoutes = DrawerRoutes;