Couldn't get param in my tabs - react-native

I have Login and MAIN screen with 2 tabs...I'm passing user to MAIN screen with navigate('MAIN',{user: user} and I couldn't get that user in my MAIN with this.props.navigation.getParam('user'). My error is: undefined
When I debug with :
Reactotron.log(this.props); I'm getting undefined in my Main screen in constructor.
My code in App.js where is routes
const Routes = createStackNavigator(
{
Login: {
screen: Login,
navigationOptions: ({ navigation }) => ({
header: null,
}),
},
Main: {
screen: MainScreenRoutes,
navigationOptions: ({navigation}) => ({
header: null,
}),
},
},
{
initialRouteName: 'Login',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
export default Routes;
Code in MainRoutes:
let headerDefaultNavigationConfig = {
header: props => <CustomHeader {...props} />,
...HeaderStyles
};
const Tab1 = createStackNavigator(
{
Domov: {
screen: HomeScreen,
navigationOptions: {
},
},
},
{
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig
}),
}
);
const Tab2 = createStackNavigator(
{
Dnevnik: {
screen: Diary,
navigationOptions: {
},
}
},
{
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig
}),
}
);
const bottomTabs = createBottomTabNavigator(
{
Domov: Tab1,
Dnevnik: Tab2,
},
{
initialRouteName: "Domov",
navigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Domov') {
//iconName = `home${focused ? '' : '-outline'}`;
iconName='home';
} else if (routeName === 'Dnevnik') {
//iconName = `ios-calendar${focused ? '' : '-outline'}`;
iconName='ios-calendar';
}
// if focused return view with line
if(focused) {
return (
<View style={styles.item}>
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
<View style={styles.line}></View>
</View>
);
} else {
return(
<Icon name={iconName} style={{fontSize: 20, color: '#FFF'}} />
)
}
},
}),
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: 'white',
showLabel: false,
inactiveTintColor: '#4C2601',
style: {
backgroundColor: '#033D51',
},
labelStyle: {
fontSize: 12,
lineHeight: 30,
},
},
swipeEnabled: true,
});
const All = createStackNavigator(
{
"Home":{
screen: bottomTabs,
navigationOptions: {
header: null,
},
},
"MyProfil":{
screen: MyProfil,
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig,
headerTitle: 'Moj profil',
}),
},
"Help": {
screen: Help,
navigationOptions: ({ navigation }) => ({
...headerDefaultNavigationConfig,
headerTitle: 'Pomoč',
}),
}
},
{
initialRouteName: 'Home',
headerMode: 'screen',
navigationOptions: {
...HeaderStyles,
animationEnabled: true
}
}
);
export default All;
Code in HomeScreen: That alert gives me undefined
constructor(props) {
super(props);
let user = props.navigation.getParam('user');
alert(user);
}
Code in Login.js where I navigate to that screen with tabs;
var obj = {
id: json.user.id,
lastname: json.user.lastname,
name: json.user.name,
email: json.user.email,
user: json.user.user,
};
_storeData(obj);
setTimeout(() => {
navigate("Main",{user: JSON.stringify(obj)});
},1300);

This is good :
this.props.navigation.navigate("HomeScreen", { user :user });
try this :
let user = props.navigation.state.params.user ;
EDIT :
as the constructor is called only one time for each app start try this
import _ from "lodash";
...
constructor(props){ super(props) ; console.log("main constructor ") ; ... }
componentWillReceiveProps(nextProps) {
console.log(JSON.stringify(nextProps.navigation.state.params))
if (_.has(nextProps, "navigation.state.params.user")) {
console.log(nextProps.navigation.state.params.user );
this.setState({ user: nextProps.navigation.state.params.user })
}
}
EDIT 2
in my createStackNavigator in dont have
navigationOptions: { header: null},
just simple stack1: { screen: stack1 },
but in my stack screen component i have this
export default class stack1 extends React.PureComponent {
static navigationOptions = ({ navigation }) => ({ header: null });
constructor (props) {
super(props);
this.state = { };
}
componentDidMount() {
this.setState({ obsToEdit: this.props.navigation.state.params.obs, dataready: true });
}
}

Related

Accessing Context Inside of TabNavigator? React Native

I currently have a tab navigator nested inside a stack navigator.
I've been trying to adjust my tabnavigator so it's able to leverage the useContext() hook to conditionally display a tab but haven't had any luck.
Here's my navigation.js file:
const TabNavigator = createBottomTabNavigator(
{
...(myInfo
? {
MyInfo: {
screen: MyInfo,
navigationOptions: {
tabBarIcon: ({ focused }) => {
let source;
focused
? (source = require('../assets/MyInfo_Inactive.png'))
: (source = require('../assets/MyInfo_Inactive.png'));
return <Image style={{ marginTop: 30 }} source={source} />;
},
},
},
}
: {}),
Account: {
screen: Account,
navigationOptions: {
tabBarIcon: ({ focused }) => {
let source;
focused
? (source = require('../assets/Account_Inactive.png'))
: (source = require('../assets/Account_Inactive.png'));
return <Image style={{ marginTop: 30 }} source={source} />;
},
},
},
},
{
defaultNavigationOptions: {
tabBarOptions: {
showLabel: false,
},
},
},
);
const MainStackNavigator = createStackNavigator(
{
Tabs: {
screen: TabNavigator,
},
Login: {
screen: Login,
},
},
{
initialRouteName: 'Login',
headerMode: 'none',
},
);
export default MainStackNavigator;
Where 'myInfo' would come from my context.
and my App.js file:
const AppContainer = createAppContainer(MainStackNavigator);
const App: () => React$Node = () => {
return (
<AccountProvider>
<AppContainer />
</AccountProvider>
);
};
export default App;
Any help is super appreciated as I'm new to React Native and have been trying to find an answer that works for quite some time.
Thanks!

Get name of previous route to go back to

I have nested stacks in my app. With two different headers.
I have a reset but this just send the user back to the home screen regardless. How can I get the previous route?
resetForm() {
const { dispatch } = this.props.navigation;
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Drawer" })]
});
this.props.navigation.dispatch(resetAction);
}
App Navigator:
const config = {
contentOptions: {
activeTintColor: "#e91e63",
inactiveTintColor: "#ffffff",
itemStyle: {
flexDirection: "row-reverse"
}
},
drawerWidth: 300,
overlayColor: "#003366",
drawerPosition: "right",
drawerBackgroundColor: "#009999",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
};
const withHeader = (
screen: Function,
routeName: string,
Header
): StackNavigator =>
createStackNavigator(
{
[routeName]: {
screen,
navigationOptions: ({ routeName, props }) => ({
header: props => <Header {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);
const routes = {
VideoEpisodes: {
screen: withHeader(VideoEpisodesScreen, "Video Episodes", DrawerHeader)
},
TestYourself: {
screen: withHeader(TestYourselfScreen, "Test Yourself", DrawerHeader)
},
MyResults: {
screen: withHeader(MyResultsScreen, "My Results", DrawerHeader)
},
BookmarkedVideos: {
screen: withHeader(
BookmarkedVideosScreen,
"Bookmarked Videos",
DrawerHeader
)
},
About: {
screen: withHeader(AboutScreen, "About", DrawerHeader)
}
};
const NestedDrawer = createDrawerNavigator(routes, config);
const MainStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
},
Drawer: {
screen: NestedDrawer,
navigationOptions: ({ props }) => ({
header: () => null
})
},
VideoPlayer: {
screen: VideoPlayerScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);

Backhandler quits app instead of going back to relative screen

Using nested stacks when I go back to my homescreen, my homescreen briefly shows, then the app quits. Instead of hardcoding the route to go back to, how can I go back to my homescreen without quitting the app?
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { dispatch } = this.props;
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Home" })]
});
this.props.navigation.dispatch(resetAction);
};
App navigator:
const withHeader = (
screen: Function,
routeName: string,
Header
): StackNavigator =>
createStackNavigator(
{
[routeName]: {
screen,
navigationOptions: ({ routeName, props }) => ({
header: props => <Header {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);
const routes = {
VideoEpisodes: {
screen: withHeader(VideoEpisodesScreen, "Video Episodes", DrawerHeader)
},
TestYourself: {
screen: withHeader(TestYourselfScreen, "Test Yourself", DrawerHeader)
},
MyResults: {
screen: withHeader(MyResultsScreen, "My Results", DrawerHeader)
},
BookmarkedVideos: {
screen: withHeader(
BookmarkedVideosScreen,
"Bookmarked Videos",
DrawerHeader
)
},
About: {
screen: withHeader(AboutScreen, "About", DrawerHeader)
}
};
const NestedDrawer = createDrawerNavigator(routes, config);
const MainStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
},
Drawer: {
screen: NestedDrawer,
navigationOptions: ({ props }) => ({
header: () => null
})
},
VideoPlayer: {
screen: VideoPlayerScreen,
navigationOptions: ({ props }) => ({
header: props => <BasicHeader {...props} />
})
}
},
{
initialRoute: "Home",
transparentCard: true,
cardStyle: {
backgroundColor: "transparent",
opacity: 1
},
transitionConfig: () => ({
containerStyle: {
backgroundColor: "transparent"
}
})
}
);
onBackPress = () => {
const { dispatch } = this.props;
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: "Home" })]
});
this.props.navigation.dispatch(resetAction);
return true
};

Drawer does not open on first touch

I have a header that should open a drawer once it is touched. However the current behaviour is that it shows immediately the Profile screen (the drawer does not open) on first touch. If you touch the header again then the drawer is actually shown.
import ...
const navigationOptions = (navigation) => {
return {
title: navigation.screenProps.t('app.title')
}
}
const defaultNavigationOptionsWithHeader = ({ navigation }) => {
return {
headerStyle: {
backgroundColor: Colors.backgroundColor,
},
headerTintColor: Colors.main,
headerTitleStyle: {
fontWeight: 'bold'
},
headerRight: <TouchableOpacity style={{ marginRight: 10 }} onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Ionicons
name={Platform.OS === 'ios'
? 'ios-menu'
: 'md-menu'}
size={40}
color={Colors.main}
/>
</TouchableOpacity>
}
}
const defaultNavigationOptionsWithoutHeader = ({ navigation }) => {
return {
headerStyle: {
backgroundColor: Colors.backgroundColor,
},
headerTintColor: Colors.main,
headerTitleStyle: {
fontWeight: 'bold'
}
}
}
const AuthStack = createStackNavigator(
{
Login: {
screen: LoginScreen,
navigationOptions: navigationOptions
},
Registration: {
screen: RegistrationScreen,
navigationOptions: navigationOptions
}
}, {
initialRouteName: 'Login',
defaultNavigationOptions: defaultNavigationOptionsWithoutHeader
});
const TabStack = createStackNavigator(
{
App: {
screen: TabNavigator,
navigationOptions: navigationOptions
}
}, {
defaultNavigationOptions: defaultNavigationOptionsWithHeader
}
);
const MenuStack = createStackNavigator(
{
App: {
screen: MenuNavigator,
navigationOptions: navigationOptions
}
}, {
defaultNavigationOptions: defaultNavigationOptionsWithHeader
}
);
const appNavigationOptions = (navigation) => {
return {
initialRouteName: 'Tab'
}
}
const AppStack = createSwitchNavigator(
{
Tab: TabStack,
Menu: MenuStack
},
{
defaultNavigationOptions: appNavigationOptions
}
)
export default createAppContainer(createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
Auth: AuthStack,
App: AppStack
},
{
initialRouteName: 'AuthLoading',
}
));
Does anybody know what causes this issue? The menu navigator is defined as follows:
import ...
handleHome = (navigation) => {
navigation.navigate('App')
}
handleLogout = (navigation) => {
logout();
navigation.navigate('Auth')
}
const config = Platform.select({
web: { headerMode: 'screen' },
default: {},
});
const navigationOptions = (navigation) => {
return {
header: null
}
}
const ProfileStack = createStackNavigator(
{
Map: {
screen: ProfileScreen,
navigationOptions: navigationOptions
}
},
config
);
ProfileStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('loggedin.sidebar.profile'),
drawerIcon: ({ focused }) => (<DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-contact'}`
: 'md-contact'
}
/>)
};
}
ProfileStack.path = '';
const PreferencesStack = createStackNavigator(
{
Settings: {
screen: PreferencesScreen,
navigationOptions: navigationOptions
}
},
config
);
PreferencesStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('loggedin.sidebar.preferences'),
drawerIcon: ({ focused }) => (<DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-settings'}`
: 'md-settings'
}
/>)
}
};
const LogoutStack = createStackNavigator(
{
Logout: {
screen: () => null,
navigationOptions: navigationOptions
}
},
config
);
LogoutStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('button.logout'),
drawerIcon: ({ focused }) => createDrawerIcon('log-out', focused)
};
}
const TabStack = createStackNavigator(
{
Logout: {
screen: () => null,
navigationOptions: navigationOptions
}
},
config
);
TabStack.navigationOptions = (navigation) => {
return {
drawerLabel: navigation.screenProps.t('app.title'),
drawerIcon: ({ focused }) => createDrawerIcon('home', focused)
};
}
createDrawerIcon = (icon, focused = false) => {
return <DrawerIcon
focused={focused}
name={
Platform.OS === 'ios'
? 'ios-' + icon
: 'md-' + icon
}
/>
}
const MenuDrawerItem = (props) => {
return <TouchableOpacity onPress={props.onPress} >
<View style={styles.item}>
<View style={styles.iconContainer}>
{createDrawerIcon(props.icon)}
</View>
<Text style={styles.label}>{props.text}</Text>
</View>
</TouchableOpacity >
}
const MenuDrawer = (props) => (
<ScrollView contentContainerStyle={{ flex: 1, flexDirection: 'column', justifyContent: 'space-between' }}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<MenuDrawerItem onPress={() => this.handleHome(props.navigation)} text={props.screenProps.t('app.title')} icon={'home'} />
<DrawerItems {...props} />
</SafeAreaView>
<MenuDrawerItem onPress={() => this.handleLogout(props.navigation)} text={props.screenProps.t('button.logout')} icon={'log-out'} />
</ScrollView>
);
const menuNavigator = createDrawerNavigator({
ProfileStack,
PreferencesStack
}, {
drawerPosition: 'right',
contentComponent: props => <MenuDrawer {...props} />,
contentOptions: {
activeTintColor: Colors.main
},
initialRouteName: 'ProfileStack'
}
);
menuNavigator.path = ''
export default menuNavigator
const styles = ...
That's probably you might have something other in focus.
May be Keyboard, TextField, Or some other things which are in focus and when you click for the first time the focus gets removed and when you press for the second time the drawer gets opened.
Try calling an alert instead of opening the drawer on button press and then debug that. That will troubleshoot the issue

Remove the navigation header from the react-native screen - stack navigation

I have a screen which has tab-bar navigation where each screen is of type stack navigation with a couple of screens defined in each. When I navigate from FamilyMembers to SingleContact screen I don't want to see the navigation bar with the back button on top. I want my view (the blue one) in single contact to start from the top. But it appears although I set the header to null! Please help.
//------------------- Single Contact Screen----------//
import { Text, AsyncStorage, Image, FlatList, Alert, ActivityIndicator, Platform, StyleSheet, View } from 'react-native';
import { Icon, Container, Spinner, Content, Left, Right, Header, ListItem } from 'native-base'
import profileService from '../services/Api/ProfileService';
import { SafeAreaView } from 'react-navigation';
HEADER_MAX_HEIGHT = 100
HEADER_MIN_HEIGHT = 60
PROFILE_IMAGE_MAX_HEIGHT = 80
PROFILE_IMAGE_MIN_HEIGHT = 40
export default class SingleContact extends Component {
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
return (
<SafeAreaView>
<View style={{ flex: 1 }}>
//--------------------App.js navigation setup --------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact"
}
}
},
}
, {
mode: 'modal',
headerMode: 'none'
});
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
FamilyMembersStack: {
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
},
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
HomeScreenStack.navigationOptions = {
tabBarLabel: 'My info',
tabBarIcon: ({ tintColor }) => (
<FaIcon name="user" size={20} color={tintColor} />
),
};
const ScheduleScreenStack = createStackNavigator({
Schedule: {
screen: ScheduleScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ScheduleScreenStack.navigationOptions = {
tabBarLabel: 'Find a class',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const ShopScreenStack = createStackNavigator({
Shop: {
screen: ShopScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
ShopScreenStack.navigationOptions = {
tabBarLabel: 'Get a pass',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-basket" size={20} color={tintColor} />
),
};
const NotificationsScreenStack = createStackNavigator({
Notifications: {
screen: NotificationsScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
}
});
NotificationsScreenStack.navigationOptions = {
tabBarLabel: 'Notifications',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-alert" size={20} color={tintColor} />
),
};
const EventsStack = createStackNavigator({
Events: {
screen: Events,
navigationOptions: ({ navigation }) => {
return {
tabBarLabel: "Events",
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} />
),
headerLeft: (
<Icon name="md-menu" style={{ paddingLeft: 10 }}
onPress={() => navigation.openDrawer()}
size={30} />
)
}
}
}
});
EventsStack.navigationOptions = {
tabBarLabel: 'Events',
tabBarIcon: ({ tintColor }) => (
<Icon name="md-calendar" size={20} color={tintColor} />
),
};
const DashboardTabNavigator = createBottomTabNavigator({
HomeScreenStack,
ScheduleScreenStack,
ShopScreenStack,
NotificationsScreenStack
},
{
navigationOptions: ({ navigation }) => {
const { routeName } = navigation.state.routes[navigation.state.index];
return {
header: null,
headerTitle: routeName,
}
},
tabBarOptions: {
activeTintColor: 'white',
inactiveTintColor: 'silver',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'rgba(24,130,201,1);',
},
}
}, { initialRouteName: HomeScreenStack }
);
const DashboardStackNavigator = createStackNavigator({
DashboardTabNavigator: DashboardTabNavigator
});
const AppDrawerNavigator = createDrawerNavigator({
Dashboard: {
screen: DashboardStackNavigator
}
}, {
contentComponent: props => <DrawerContent {...props} />
});
const AppSwitchNavigator = createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
Login: { screen: Login },
Dashboard: { screen: AppDrawerNavigator }
}, {
initialRouteName: 'AuthLoading',
}
);
const AppContainer = createAppContainer(AppSwitchNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
Did you already modify your FamilyMembersStack inside HomeScreenStack like this?
const HomeScreenStack = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => {
return {
header: null,
}
},
},
// modify this Stack
FamilyMembersStack:{
screen: FamilyMembersStack,
navigationOptions: ({ navigation }) => {
return {
header: null
}
}
}
AttendanceHistory: {
screen: AttendanceHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Attendance history"
}
}
},
OrderHistory: {
screen: OrderHistory,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Order history"
}
}
}
});
Follow up answer, remove the following. so that the header will render on the designated screen:
export default class SingleContact extends Component {
static navigationOptions = {
header: null, // remove this
}
constructor(props) {
super(props);
this.state = { userName: "", contacts: [], userID: "", cookie: null, memberShips: [] };
}
async componentDidMount() {
}
onDataLoaded(result, userName) {
}
render() {
//------------------------------//
const FamilyMembersStack = createStackNavigator({
FamilyMembers: {
screen: FamilyMembers,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Family members",
header:null
}
}
},
SingleContact: {
screen: SingleContact,
navigationOptions: ({ navigation }) => {
return {
headerTitle: "Contact",
header:null // and remove this
}
}
},
});