How to get navigation object outside Screen - react-navigation

I have the following code in the App.tsx:
export default function App() {
...
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="StackNavigation"
drawerContent={(props) => <MainPageDrawer {...props} />}
screenOptions={{ swipeEnabled: false }}
>
<Drawer.Screen name="StackNavigation" component={StackNavigator} />
</Drawer.Navigator>
</NavigationContainer>
);
...
}
As you see, the MainPageDrawer component isn't inside the Drawer.Screen component. But I still need to get access to navigation object inside MainPageDrawer. When I do something lake this inside MainPageDrawer:
const navigation = useNavigation<MainScreenNavigationProp>();
I get the following error:
Couldn't find a navigation object. Is your component inside a screen in a navigator?
What is the right way to get access to the navigation object outside Screen component?

Solution: I figured out that useNavigation won't work anyway if it is outside Screen, BUT this:
(props) => <MainPageDrawer {...props} />
still pass navigation through props, so you can easily access it without useNavigation. I simply restructured navigation:
function MainPageDrawer({ navigation }) {
...
}
And it works

Related

TypeError: undefined is not an object (evaluating 'Navigation.navigate')

I am having an error which is showing
TypeError: undefined is not an object (evaluating 'Navigation.navigate')
i were tried to fix this error but didnt work, I also search the error on network but i am getting other content steps
There My Codes:
export const App = ({ Navigation }) => {
/*My Codes*/
<TouchableOpacity onPress={() => Navigation.navigate("DetailsPage2")>
/*My Object*/
</TouchableOpacity>
I wanted To Switch Pages By clicking on the object using onPress and use arrow function but it shows the error, I tried These Steps to resolve it but it also didnt work These are The steps below which i used to fix the error
onPress={() => Navigation.getParam("DetailsPage2") and
onPress={() => Navigation.push("DetailsPage2")
I imported all the imports which i need Like
import React, { useState, useRef, useEffect, createRef, useCallback, } from "react"; import { View, Text, Image, ScrollView, TextInput, StyleSheet, Switch, Animated, Dimensions, Vibration, Alert, KeyboardAvoidingView, Platform, TouchableWithoutFeedback, TouchableOpacity, SafeAreaView, } from "react-native"; import { Svg, Path, Defs, RadialGradient, LinearGradient, Stop, Ellipse, Rect, } from "react-native-svg";
Sorry I Cannot Show My Main Code, If I Show It.
It Could Be Stolen
This error is occurring because the 'Navigation' object is not defined in the App component. It is not being imported correctly.
Make sure that the navigation object is being passed in as a prop to the App component and that it is being imported correctly.
Replace Navigation with navigation:
export const App = ({ navigation }) => {
/*My Codes*/
<TouchableOpacity
onPress={() => navigation.navigate("DetailsPage2")>
/*My Object*/
</TouchableOpacity>
}
Here is the official doc related to this issue reference link.
& React Navigation official website for explore more Link.

React navigation createMaterialTopTabNavigator inside a screen

React navigation createMaterialTopTabNavigator shows a pretty cool setup at the top of their documentation page:
Notice that the top navigator stack seems to be inside a screen. There is a title at the top "Material Top Tabs" and we can go back to "Examples"
Funny enough, this setup is not given in any of the examples.
I would like to have the same setup and be able to navigate to a specific tab from another screen.
Could someone please share an example code for it?
What I currently have is a basic bottom tab navigation with a
<BottomTab.Screen
name="Tabs"
component={TabsNavigator}
/>
and then
function TabsNavigator() {
const MyTabs = createMaterialTopTabNavigator();
return (
<MyTabs.Navigator
<MyTabs.Screen name="Upcoming" component={TabsUpcomingScreen} />
<MyTabs.Screen name="Past" component={TabsPastScreen} />
</MyTabs.Navigator>
);
}
Although this works when doing navigation.navigate('Tabs', { screen: 'Upcoming' });, I am missing the screen containing the tabs... or the "Tabs" screen (as in the example, it is the "Material Top Tabs" screen)
I could do something like this:
function TabsNavigator() {
const TabsStack = createStackNavigator();
return (
<TabsStack.Navigator>
<TabsStack.Screen name="Tabs" component={TabsScreen} options={{ headerTitle: 'Tabs' }} />
</TabsStack.Navigator>
);
}
function TabsScreen() {
const MyTabs = createMaterialTopTabNavigator();
return (
<MyTabs.Navigator
<MyTabs.Screen name="Upcoming" component={TabsUpcomingScreen} />
<MyTabs.Screen name="Past" component={TabsPastScreen} />
</MyTabs.Navigator>
);
}
But then I am unable to navigate to a specific tab with navigation.navigate('Tabs', { screen: 'Upcoming' });
If you want to navigate to some tab inside of createMaterialTopTabNavigator.Instead of navigation.navigate('Tabs', { screen: 'Upcoming' }) use navigation.jumpTo('Tabs', { name: 'Upcoming' });
https://reactnavigation.org/docs/material-top-tab-navigator#jumpto

React-Navigation v4 pass state from child to parent on back press

I need to pass state from my child screen to the parent screen . I am having difficulties doing this. I am letting the user press a button to navigate to the child screen. After filling info in the child screen I am trying to pass the value back to the parent screen with props.navigation.goBack() Can someone help me out with this.
I am using react navigation v4
Parent screen:
const Parent = (props) => {
const [day, setDay] = useState("");
return (
<TouchableOpacity
onPress={() =>props.navigation.navigate({ routeName: 'Child' })}>
</TouchableOpacity>
);
};
Child screen (I want to pass the day state back to the parent)
const Child = props => {
const [day, setDay] = useState("");
return (
<View style={styles.container}>
<TextInput onChange={(text)=> setDay(text)}/>
<Button onPress={()=>props.navigation.goBack()}/>
</View>
);
};
If it is not possible to use the normal navigation way maybe try to build your own back function and pass params with it.
Take a look at this maybe:
goBack() {
const { navigation } = this.props;
navigation.goBack();
navigation.setParam({ day: dayData});
}
then the call would be :
<Button onPress={()=>this.goBack()}/>
you can get the param with :
this.props.navigation.getParam("day")
try it somehow like this - if it does not work try the calls with this.props.navigation...
or only with navigation.goBack() and so on because I am not sure wich syntax will work for you.

Reset stack inside a tab on tab double press using React Navigation 5

I am wondering how to reset a stack inside a BottomTabNavigator if the Tab is focused and pressed.
This is the code I have so far:
const Stack = createStackNavigator<MainStackParams>()
const BottomTab = createBottomTabNavigator<TabNavigatorParams>()
const navigationRef = React.useRef()
> Blockquote
<NavigationContainer ref={navigationRef}>
<Stack.Navigator mode="modal">
<Stack.Screen
name={MainAppRoute.BOTTOM_TAB_NAVIGATOR}
component={BottomTabNavigator}
/>
...
</Stack.Navigator>
</NavigationContainer>
function BottomTabNavigator() {
return (
<BottomTab.Navigator>
<BottomTab.Screen
name={TabNavigatorRoute.SOME_STACK}
component={SomeStack}
listeners={{tabPress: e => {
// TODO: Reset stack in current tab (unsure how to do this)
}}}
/>
...
</BottomTab.Navigator>
)
}
In the TODO (in the code snippet) the following should probably be done:
Get navigationRef from app NavigationContainer
Check if the selected BottomTab is focused (to determine a double press)
e.preventDefault
reset SomeStack (unsure how to get the navigation object a stack inside a BottomTabNavigator)
Have any one been able to do this yet?
Appreciate all answers :)
Okey, basically you have 2 options to manage this, first is to check navigation state, but as i found out, it works only on IOS device, android does not do anything.
This piece of code navigated to first screen from this stacknavigator
<Tab.Screen name={`DeviceNavigatorTab`} component={DeviceNavigator} options={{
tabBarIcon: ({tintColor}) => <Image source={require('../../images/feather_home-menu.png')} style={{width: 26, height: 26, tintColor}}/>,
}} listeners={({ navigation, route }) => ({
tabPress: e => {
if (route.state && route.state.routeNames.length > 0) {
navigation.navigate('Device')
}
},
})} />
The other solution, and even better, works on android and IOS operating systems
DeviceNavigatorTab this is tab navigator screen name, {screen: 'Device'} is the first stack screen name in sub stack navigator, hope it helps
<Tab.Screen name={`DeviceNavigatorTab`} component={DeviceNavigator} options={{
tabBarIcon: ({tintColor}) => <Image source={require('../../images/feather_home-menu.png')} style={{width: 26, height: 26, tintColor}}/>,
}} listeners={({ navigation }) => ({
tabPress: e => {
navigation.navigate('DeviceNavigatorTab', { screen: 'Device' });
},
})} />
It is not actually resetting the navigators, it just goes to specified screen inside that tab navigator.

back button with react-navigation on specific screen dynamically

on react-navigation i am trying to navigate to a specific screen which depends on some condition!
Below it is pointing to 'App' page right now
but sometimes i need it to go to 'Main' page
static navigationOptions = ({ navigation }) => {
return {
title: 'Tools',
headerLeft: (
<Button
onPress={() => navigation.navigate('App')}
title="Back"
/>
),
};
};
when i use state or function
for example
...
...
onPress={() => navigation.navigate(this.someFunction())}
...
...
there is an error undefined is not an object
so how do I point dynamically the desirable page to navigate to?
if came from any screen , want to go back dynamic without defining the screen name in navigation . Use this method :
onPress={()=>navigation.goBack()}
navigation.goBack() method will take you directly on the screen where it came from .

Resources