Im using react-navigation version 3.3.2 and the current transition between loaded stacks of screens is it will appear sliding from bottom.
import { createAppContainer, createBottomTabNavigator, createStackNavigator } from 'react-navigation';
const TabNavigator = createBottomTabNavigator({
Home: createStackNavigator({...screens}),
Settings: createStackNavigator({...screens}),
}, {
...
})
const AppContainer = createAppContainer(TabNavigator);
How can I change it to transition of current stack fading out and next stack fading in?
Related
I am working with React Native createBottomTabNavigator and see that:
lazy - Defaults to true. If false, all tabs are rendered immediately. When true, tabs are rendered only when they are made active for the first time. Note: tabs are not re-rendered upon subsequent visits.
https://reactnavigation.org/docs/bottom-tab-navigator/
Where do I put the attribute "lazy" and set it to false if I want to reload the Connection page every time I click on the Connect navigation tab?
import { createStackNavigator, createAppContainer, createBottomTabNavigator, createSwitchNavigator } from 'react-navigation';
import ...
const RegisterScreens = createSwitchNavigator({
Phone: PhoneLoginScreen,
Register: RegisterScreen
});
const switchNavigator = createSwitchNavigator({
SplashScreen,
TutotialScreen,
loginFlow: createStackNavigator({
Main: MainScreen,
EmailLogin: EmailLoginScreen,
PhoneLogin: RegisterScreens
}),
mainFlow: createBottomTabNavigator({
Home: createStackNavigator({
HomeScreen,
AccountScreen
}),
Connect : ConnectionsScreen,
Chat: createStackNavigator({
AllChatScreen,
SingleChat
})
})
});
const App = createAppContainer(switchNavigator);
export default() => {
return (
<AuthProvider>
<App ref={(navigator)=> {setNavigator(navigator)}}/>
</AuthProvider>
)
};
I am using hooks and want to reload the Connection page because of a callout happening in useEffect()
I have a root StackNavigator which has other two navigator
1 stack navigator (login, signup)
2 tab navigator (home, profile, settings)
so when user login success how can I nevigate to tabNavigator from rootNavigator?
import React from 'react';
import { createStackNavigator, createAppContainer } from 'react-navigation'
import authNavi from './AuthRoute'; /// this is StackNavigator with login signup screen
import appNavi from './AppRoute' /// this is tabNAvigator with profile home setting screen
const RootRoute = createStackNavigator({
auth: {screen: authNavi },
app: {screen: appNavi }
})
const RootNavi = createAppContainer(RootRoute);
export default RootNavi; /// this is rootNavigator whih is rendered in App.js
here is the image of App.js and RootRouter
You could navigate from your auth stack to you tabNavigator by:
this.props.navigation.navigate('app');
Suggestion
I suugest you replace your main StackNavigator by a SwitchNavigator ... cause after the user is logged in successully, you won't need them to have access to your auth flow again.
By using Switch Navigator you can achieve this.
import createSwitchNavigator from react-navigation
eg:
import {
createAppContainer,
createStackNavigator,
...
createSwitchNavigator
} from "react-navigation";
After that add switch navigator.
...
const switchNavigator = createSwitchNavigator(
{
LoginStack: authNavi,
AppTabs: appNavi
},
{ headerMode: "none", initialRouteName: "LoginStack" }
);
const App = createAppContainer(switchNavigator);
export default App;
And when you want to change to home, use this
this.props.navigation.navigate("AppTabs");
It will switch the navigation to TabBar navigation.
I am working on a React Native project (wrapped-up using Expo) with react navigation v3. So, now I decided to enable real-time push notifications provided by Expo. My goal is to submit some custom data together with the push notification itself and then, once it goes on the device and I open the notification to navigate/route/redirect the app to a specific screen that I have defined. I have configured the notifications, I get expo tokens, I receive the notification, it goes in the handler but when I try to apply the navigation that I use throughout my whole app:
this.props.navigation.navigate('RouteName', {data:{...}})
I am getting undefined. I guess we are somehow not in the context of react navigation and that's why some other approach is required. I just don't know what it is.
The structure of my app is as follows:
HomeStack.js
import { createStackNavigator } from 'react-navigation';
import HomeScreen from '../screens/HomeScreen'
import MailboxItemsScreen from '../screens/MailboxItemsScreen'
import MailboxItemDetailsScreen from '../screens/MailboxItemDetailsScreen'
export default createStackNavigator({
Home: HomeScreen,
MailboxItems: MailboxItemsScreen,
MailboxItemDetails : MailboxItemDetailsScreen
});
SettingsStack.js
import { createStackNavigator } from 'react-navigation';
import SettingsScreen from '../screens/SettingsScreen'
export default createStackNavigator({
Settings: SettingsScreen
});
AppNavigator.js
import React from 'react';
import { createBottomTabNavigator, createAppContainer } from 'react-navigation';
import Icon from 'react-native-vector-icons/Ionicons'
import HomeStack from './HomeStack'
import SettingsStack from './SettingsStack'
const TabNavigator = createBottomTabNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
tabBarIcon:({tintColor})=>(
<Icon name="ios-home" color={tintColor} size={24}/>
)
}
},
Settings: {
screen: SettingsStack,
navigationOptions: {
tabBarIcon:({tintColor})=>(
<Icon name="ios-settings" color={tintColor} size={24}/>
)
}
}
});
export default createAppContainer(TabNavigator);
Then I use the TabNavigator in my App.js. It is quite common structure I just don't know how to do the navigation between screens in my push notification handler method.
It is likely that you already added a listner at root component's constructor or componentDidMount() like that:
Notifications.addListener(this._handleNotifications)
and as the expo document says, you tried to navigate to other screen in _handleNotifications function.
In my case, although navigation structure is slightly different from yours, I added listner at HomeScreen's componentDidMount() and defined _handleNotifications function within HomeScreen component, not at root component (App.js).
Brief version of my `_handleNotifications function is as below:
_handleNotifications = async (notification) => {
const {a, b, c} = notification.data;
const {origin} = notification;
if (origin === 'selected') {
this.props.navigation.push('History', {
a,
b,
c,
})
} else { // origin is 'received'
// show notification at the top of my app instead of navigate to other screen
}
}
if user press notification, then notification is delivered to my app's _handleNotifications function, and since the origin is 'selected', I pushed to other screen called 'History' with parameters received from notification.data.
In my case, that works very well.
Since, the behavior of Android and iOS differs slightly, the event handler should do some more jobs.
I implemented it with Expo v32.0.0 and react navigation 3.x.x.
Hope this helps.
I'm learning react native with configuring tabNavigator, DrawerNavigator, and StackNavigator into one without NativeBase or Expo with a single react-navigation library.
I achieved it but there comes an error when I perform some specific sequence in my application.
The application starts with Tab Screen. -> Change Tab -> Open Drawer -> Goto Stack -> open Drawer and then go to Tabs gives this error.
Here is my code :
App.js
import React from 'react';
import {Drawer} from "./src/navigation/MergedNavigator";
import {View,Text} from "react-native";
const App = () => (
<View style={{flex: 1,backgroundColor: '#293656'}}>
<Drawer />
</View>
);
export default App;
MergedNavigator.js
import {DrawerNavigator,StackNavigator,createBottomTabNavigator} from 'react-navigation';
// stack navigation screens
import DetailScreen from '../screens/detail';
import MainScreen from '../screens/main';
import ForgotScreen from '../screens/ForgotScreen';
import RegisterScreen from '../screens/RegisterScreen';
// tab navigator screens
import LoginScreen from '../screens/Login';
import TabOne from '../screens/tabA';
import TabTwo from '../screens/tabB';
//plain
export const stack = StackNavigator({
DetailScreen:{screen:DetailScreen},
MainScreen:{screen:MainScreen}
},{
initialRouteName:'DetailScreen'
});
const secondStack = StackNavigator({
RegisterScreen:{screen:RegisterScreen},
ForgotScreen:{screen:ForgotScreen}
},{
initialRouteName:'ForgotScreen'
})
export const Tabs = createBottomTabNavigator({
Login:{screen:LoginScreen},
TabOne:{screen:secondStack},
TabTwo:{screen:TabTwo}
},{
animationEnabled:true
})
export const Drawer = DrawerNavigator({
Tabs:{screen:Tabs},
Stack:{screen:stack}
})
And all other imported stack screen has nothing but the title.
What's the problem here with my code? Or is there any better way I can achieve these all 3 Navigators with only react-navigation?
There is an issue with the sub actions being reset inside the Stack which can be seen here
Therefore the workaround for this issue would be to wrap your createBottomTabNavigator inside a createStackNavigator with headerMode: none in order to achieve the desired effect.
Info
By adding a StackNavigator nested directly within a DrawerNavigator, the sub actions will be reset only to the StackNavigator defined and won't affect the child screen states, therefore it won't throw the error, as mentioned in the code
if (route.index !== undefined && route.index !== 0) {
subAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: route.routes[0].routeName,
}),
],
});
}
MergedNavigator.js
import ForgotScreen from '../screens/ForgotScreen';
import RegisterScreen from '../screens/RegisterScreen';
// tab navigator screens
import LoginScreen from '../screens/Login';
import TabOne from '../screens/tabA';
import TabTwo from '../screens/tabB';
//plain
export const stack = StackNavigator({
DetailScreen:{screen:DetailScreen},
MainScreen:{screen:MainScreen}
},{
initialRouteName:'DetailScreen'
});
const secondStack = StackNavigator({
RegisterScreen:{screen:RegisterScreen},
ForgotScreen:{screen:ForgotScreen}
},{
initialRouteName:'ForgotScreen'
})
export const Tabs = createBottomTabNavigator({
Login:{screen:LoginScreen},
TabOne:{screen:secondStack},
TabTwo:{screen:TabTwo}
},{
animationEnabled:true
})
const TabStack = createStackNavigator({ //... Adding the Stack here
Tabs: {screen: Tabs}
}, {
headerMode: 'none'
})
export const Drawer = DrawerNavigator({
Tabs:{screen:Tab},
Stack:{screen:stack}
})
Here's a modified Snack with header's enabled
import { StackActions, NavigationActions } from 'react-navigation';
let { navigation } = this.props;
let resetAction = StackActions.reset({
key: undefined,
index: 0,
actions: [NavigationActions.navigate({ routeName: 'YourScreen' })],
});
navigation.dispatch(resetAction);
When you set the key to undefined, the navigator uses the actual stack, not the root.
First of all your main issue is you cann't create more than one StackNavigator() on your code.
Please try different navigator for redirection like below example code.
import {DrawerNavigator,StackNavigator,createBottomTabNavigator,createMaterialTopTabNavigator} from 'react-navigation';
// stack navigation screens
import DetailScreen from '../screens/detail';
import MainScreen from '../screens/main';
import ForgotScreen from '../screens/ForgotScreen';
import RegisterScreen from '../screens/RegisterScreen';
// tab navigator screens
import * as TAB from '../tab';
export const stack = StackNavigator({
DetailScreen:{screen:DetailScreen},
MainScreen:{screen:MainScreen}
},{
initialRouteName:'DetailScreen'
});
const secondStack = createMaterialTopTabNavigator({
RegisterScreen:{screen:RegisterScreen},
ForgotScreen:{screen:ForgotScreen}
},{
initialRouteName:'ForgotScreen'
})
export const Tabs = createBottomTabNavigator({
Login:{screen:TAB.Login},
TabOne:{screen:secondStack},
TabTwo:{screen:TAB.TabB}
},{
animationEnabled:true,
initialRouteName:'Login'
})
export const Drawer = DrawerNavigator({
Tabs:{screen:Tabs},
Stack:{screen:stack}
},
{
animationEnabled:true,
initialRouteName:'Tabs'
})
hope above code snippet is useful for you.
I have a Drawer Navigator with 2 screens, Home and Profile. What I need is, when I click in a TouchaleOpacity, change the screen from home to profile, how can I do this?
import { DrawerNavigator } from 'react-navigation';
import JsHome from './JsHome'
import JsProfile from './JsProfile'
const DrawerExample = DrawerNavigator({
JsHome : {
screen: JsHome
},
JsProfile : {
screen: JsProfile
},
}
PS: the TouchableOpacity are in another js file
each screen has navigation props. use this.props.navigation.navigate('JsProfile') in your touchable opacity