I am using react navigation in my app, and when i am using reset for clearing the stack and navigating to other screen , it is showing weird animation, like first all the screens that were in stack are poped and then it navigates to the new screen.
Here is the code
//code for resetting the stack
Login.js
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'Home'})
],
})
this.props.navigation.dispatch(resetAction)
Route.js
Home: {
screen: Tab,
navigationOptions: {
...headerStyle,
}
},
Intro: {
screen: IntroScreen,
navigationOptions: {
header: null
}
},
LogIn: {
screen: LogIn,
navigationOptions: {
...headerStyle,
title: 'LogIn',
}
},
So it first goes to into screen and then to home screen, how to fix this so it directly goes to Home screen
If you remove
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'Home'})
],
})
this.props.navigation.dispatch(resetAction)
from your Login.js then the stack navigator automatically goes to the first screen in the StackNavigator , which in this case will be your Home: {...} screen.
There is no need for you to reset the stack.
If you want to navigate to another screen by pressing a button for example then use
import React, { Component } from 'react';
import {
View,
Button,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
export default class Initial extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Button
onPress={() => navigate('Login')}
title="Go to Login"
color="#357DED"
/>
</View>
);
}
}
Related
I have BottomTabNavigator with 4 tabs I have the structure as in the screenshot below. That is the View below the BottomTabBar which is achieved but, the problem is I am not able to navigate from the Home/search tab to any other tab. Also, I tried with passing navigation in <Appcontainer /> as given below in the code but it is also not working.
I am using react-navigation v3.11.2
Is there any other way to pass navigation prop in <Appcontainer />. Or Any other method so I can able to navigate in BootomTabs.
const Tabs = createBottomTabNavigator(
{
Home: {
screen: Home,
},
Search: {
screen: Search,
},
Add: {
screen: () => null,
navigationOptions: () => ({
tabBarOnPress: async ({ navigation }) => {
navigation.navigate('Upload');
}
}),
},
Profile: {
screen: Profile,
},
},
);
export default class ParentTabs extends React.Component {
render() {
const { navigate } = this.props;
return (
<View>
<AppContainer navigate={navigate} />
<View>
<Text>My Text</Text>
</View>
</View>
);
}
}
const AppContainer = createAppContainer(Tabs);
navigation.navigate('Upload');
You cannot navigate to any random component. Upload should be a route name defined in your tab navigator.
Otherwise, you need to trigger Upload logic inside your Add screen
I used createMaterialTopTabNavigator to create footer tab, like as below:
const TabNavigator = createMaterialTopTabNavigator(
{
HomeScreen: HomeScreen,
UserScreen: UserScreen,
},
{
initialRouteName: 'HomeScreen',
navigationOptions: {
header: null,
},
tabBarPosition: 'bottom',
tabBarComponent: FooterTabs,
},
);
and in FooterTabs on home screen button, i have this code:
if (this.props.navigation.state.index === 0) {
// i want call scrollToUp function in HomeScreen component
}
i want when user is in HomeScreen and press on home button react call scrollToUp method in HomeScreen.
===== resolved:
I added this code to HomeScreen:
componentDidMount() {
this.props.navigation.setParams({
onFocus: this.scrollToUp,
});
}
and edit FooterTabs like as below:
if (this.props.navigation.state.index === 0) {
this.props.navigation.state.routes[0].params.onFocus();
}
Hav you trid putting your Homescreen in a scrollView , and when the user presses home button ,
class HomeScreen extends Component {
render(){
return(
< ScrollView ref={(ref) => { this.scrollListReftop = ref; }}>
// your code here
< /ScrollView>
)
}
}
// add this to scroll to the top of scrollView inside your componentDidMount of Homescreen
componentDidMount(){
setTimeout(() =>this.scrollListReftop.scrollTo({x: 0, y: 0, animated: true}),10);
}
Hope its clear, feel free for any doubts.
i'm new in react native. i want to add if condition in initialRouteName like code below. when "notification" variable is null move to "MemberProfile" page. but if "notification" variable is not null move to "ReviewMember" page. i try it code but still move to "MemberProfile" page. any solution?.
this is my code
var notification = null;
class DrawerMember extends Component {
constructor(props) {
super(props);
this.state = {
notifData: null
};
this.callCheck();
}
async callCheck() {
await AsyncStorage.getItem("#tryCode:notification", (err, result) => {
if (result != null) {
this.setState({
notifData: "testing data"
});
}
});
}
render() {
notification = this.state.notifData;
return <Root />;
}
}
const Root = createDrawerNavigator(
{
MemberProfile: {
screen: MemberProfileScreen
},
ReviewMember: {
screen: ReviewScreen
}
},
{
drawerPosition: "right",
initialRouteName: notification == null ? "MemberProfile" : "ReviewMember",
contentComponent: props => <SideBar {...props} />,
}
);
export default DrawerMember;
I think Root is created before the async function returns so notification is always null.
A possible way to solve this problem would be to use a SwitchNavigator as the first screen in your drawer. This navigator would be responsible for loading the notification and redirecting to the right screen.
Something along the lines of:
import React from 'react';
import { View, AsyncStorage, ActivityIndicator, StatusBar } from 'react-native';
export default class DummySwitch extends React.Component {
async componentDidMount() {
this.listener = this.props.navigation.addListener('willFocus', async () => {
const notification = await AsyncStorage.getItem('#tryCode:notification');
if (notification === null) {
this.props.navigation.navigate('MemberProfile');
}
else {
this.props.navigation.navigate('ReviewMember');
}
});
}
render() {
return (
<View>
<ActivityIndicator />
<StatusBar barStyle='default' />
</View>
);
}
}
As you can see, the switch screen just displays a loading button while accessing the async storage and deciding which route to take.
Then you define the drawer as usual but you add the switch screen as the initial route. You can also hide the label if you want by defining your own drawerLabel:
export default createDrawerNavigator({
Switch: {
screen: Switch,
navigationOptions: () => ({
drawerLabel: () => null,
}),
},
MemberProfile: {
screen: MemberProfileScreen,
},
ReviewMember: {
screen: ReviewScreen,
},
}, { initialRouteName: 'Switch' });
This is it, the drawer now selects the route based on your async storage.
I am using React Navigation. I have a 'more' button as the last item of the bottom tab navigator and I want it to open a drawer when a user clicks on it. I have tried so many things and studied so many answers but nothing works. The closest I can get is below. It brings you to a page which contains a drawer that can be opened. However, I want it to be opened when it is clicked.
So far I have this code...
const MoreStack = createDrawerNavigator({
More: { screen: More }
})
const MainTabNavigator = createBottomTabNavigator({
Home: { screen: HomeStack }
...
More: { screen: MoreStack }
})
const MainStackNavigator = createStackNavigator({
MainTabNavigator: MainTabNavigator,
})
const AppSwitchNavigator = createSwitchNavigator({
Welcome: { screen: WelcomeScreen },
Home: { screen: MainStackNavigator }
})
const AppContainer = createAppContainer(AppSwitchNavigator)
UPDATE
So a possible solution is to open the MoreStack with an initial Route that renders a FlatList as opposed to a drawer. In the MoreStack I also create all the pages I need to be included in the More FlatList. Then in the More screen I create an array with each route as an object and I link to them from the FlatList using navigation.navigate(item.name)
The problem with this, and the key to making it work like a drawer was setting the backBehavior: 'history', in the MainTabNavigator. Then, when you add a gesture handler to the 'More' screen onSwipeRight and set to navigation.goBack(null) it will return you to the previous route, making it feel like you are 'closing' the more screen.
I am not sure how this will all work once I get into more navigation situations for routes within the MoreStack, but I guess I'll deal with that when I get to it.
Your tab navigator and StackNavigator should be the MainTabNavigator s child as:
const MainTabNavigator = createBottomTabNavigator({
Home: { screen: HomeStack }
More: { screen: MoreStack }
})
const MainStackNavigator = createStackNavigator({
MainTabNavigator: MainTabNavigator,
})
const MoreStack = createDrawerNavigator({
SomePage:{screen:MainTabNavigator}//<<<<<<<<
SomeOther:{screen:MainStackNavigator}//<<<<<<<<<<
More: { screen: More }
})
const AppSwitchNavigator = createSwitchNavigator({
Welcome: { screen: WelcomeScreen },
Home: { screen: MaoreStack }//<<<<<<<<<<<<<<<<<<<<<<
})
and then give MoreStack to AppSwitchNavigator.....
You can use this code. I used the 3.x version of react-navigation
const FooterTabs = (props) => (
<Footer>
<FooterTab}>
<Button
vertical
onPress={() => props.navigation.openDrawer()}>
<Text style={styles.Text}> Menu</Text>
</Button>
</FooterTab>
</Footer>
)
const MainTabNavigator = createBottomTabNavigator({
Home: { screen: HomeStack }
...
More: { screen: MoreStack }
},{
tabBarComponent: props =>
<FooterTabs
{...props} />,
initialRouteName: "Home",
})
const MoreStack = createDrawerNavigator({
More: { screen: More }
})
const AppContainer = createAppContainer(MoreStack )
I'm working with React Native and React Navigation.
I have a component called App.js in which I declare the Drawer Navigation of React-Navigation.
In this I have an option to log out but I can not navigate to another component after removing the AsyncStorage
Does anyone know how to achieve it?
Thank you.
This is my code:
App.js
import { createDrawerNavigator, DrawerItems, NavigationActions } from 'react-navigation';
const customDrawerComponent = (props) => (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView>
<DrawerItems
{...props}
/>
<TouchableOpacity style={styles.button} onPress={this.logOut} >
<Text> Logout </Text>
</TouchableOpacity>
</ScrollView>
</SafeAreaView>
);
logOut = () => {
// NOT WORKS
// this.props.navigation.navigate('Login')
//NOT WORKS:
this.myAction();
}
myAction = () => {
const nav = NavigationActions.navigate({
routeName: 'App',
});
return nav;
};
const AppDrawNavigator = createDrawerNavigator(
{
MainComponent: { screen: MainComponent,
navigationOptions: ({navigation}) => ({
drawerLockMode: 'locked-closed'
}) },
Login: { screen: LoginComponent,
navigationOptions: ({navigation}) => ({
drawerLockMode: 'locked-closed'
}) },
User: { screen: UsersComponent }
},
{
contentComponent: customDrawerComponent,
}
);
make this as a class like
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
}
}
From your question I understand that either you want to :-
navigate from outside the components
navigate from components which do not have navigation prop.
For this I have tried 2 solutions and both work extremely fine though I based towards the second one.
First Solution
Use withNavigation from react-navigation package. If your components are deeply nested they wont have navigation prop unless u specify them manually or put them in context ;passing navigation prop becomes a real pain. So instead use withNavigation and your component would have navigation prop.
import {withNavigation} from "react-navigation";
const Component = ({navigation}) => {
const onPress = () => {
navigation.navigate(//ROUTE_NAME//)
}
return (
<TouchableOpacity onPress={onPress}>
<Text>Navigate</Text>
</TouchableOpacity>
)
}
export default withNavigation(Component);
Second Solution
Create a helper script and use that.
"use strict";
import React from "react";
import {NavigationActions} from "react-navigation";
let _container; // eslint-disable-line
export const navigation = {
mapProps: (SomeComponent) => {
return class extends React.Component {
static navigationOptions = SomeComponent.navigationOptions; // better use hoist-non-react-statics
render () {
const {navigation: {state: {params}}} = this.props;
return <SomeComponent {...params} {...this.props} />;
}
}
},
setContainer: (container) => {
_container = container;
},
reset: (routeName, params) => {
_container.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName,
params
})
]
})
);
},
goBack: () => {
_container.dispatch(NavigationActions.back());
},
navigate: (routeName, params) => {
_container.dispatch(
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName,
params
})
);
},
navigateDeep: (actions) => {
_container.dispatch(
actions.reduceRight(
(prevAction, action) =>
NavigationActions.navigate({
type: "Navigation/NAVIGATE",
routeName: action.routeName,
params: action.params,
action: prevAction
}),
undefined
)
);
},
getCurrentRoute: () => {
if (!_container || !_container.state.nav) {
return null;
}
return _container.state.nav.routes[_container.state.nav.index] || null;
}
};
In your parent component when you mount the navigation call following:-
"use strict";
import React from "react";
import App from "./routes";
import {navigation} from "utils";
class Setup extends React.Component {
render () {
return (
<App
ref={navigatorRef => {
navigation.setContainer(navigatorRef);
}}
/>
);
}
}
export default App;
Now, in your components you can directly use helpers from this script itself and navigation would be accessibly globally now.
import {navigate} from "utils/navigation";
For more details you can this thread
Your logout function is declared outside of the Navigator. This means you don't have access to the navigation prop there. However, your customDrawerComponent is a screen of your Navigator and it should have access to it.
So you can try something like this (props here are the props passed to the customDrawerComponent):
onPress={()=> {props.navigation.navigate("Login")}}
Plus your App.js seems kind of strange since you're not exporting any component. Have you pasted the whole code of App.js or just parts of it?