How can I redirect from StackNavigator screen to BottomTabNavigator screen - react-native

I'm working on an app in React-Native. How I'm trying to achieve this is by using a SignUpCompleted Flag and checking if its true/false to decide if the page should navigate to the next signup screen or just to the homepage. I have 3 screens as part of the sign-up process that I only want to be shown the 1st time the app opens. I have the 3 screens in a StackNavigator and I'm trying to navigate from the last StackNavigator screen to a BottomTabNavigator screen. Sadly I get the following error:
The action 'NAVIGATE' with payload {"name":"HomeStack"} was not handled by any navigator.
My current setup is as follows:
SignUpStack
const SignUpStack = createStackNavigator();
export default function SignUpStackScreen() {
const [signUpCompleted, setSignUpCompleted] = useState(false);
return (
<SignUpStack.Navigator initialRouteName="Welcome" screenOptions={{ headerShown: false }}>
<SignUpStack.Screen name="Welcome" component={WelcomeScreen} initialParams={{signUpCompleted}} />
<SignUpStack.Screen name="Department" component={ChooseDepartment} initialParams={{signUpCompleted}} />
<SignUpStack.Screen name="InputName" component={InputName} initialParams={{signUpCompleted, setSignUpCompleted}}/>
</SignUpStack.Navigator>
);
}
From the InputName component I try to redirect to a BottomTabNavigator Screen called homename
The redirect code is as follows: - in InputName component
<TouchableOpacity
style={[styles.shadow]}
onPress={() => {navigation.navigate("HomeName"); setSignUpCompleted(true)}}
>
The BottomTabNavigator is as follows: - I'm trying to redirect to HomeStack component
-const Tab = createBottomTabNavigator();
export default function Tabs() {
return (
<Tab.Navigator initialRouteName={homeName} >
<Tab.Screen name={ResultsName} component={ResultatenStack} />
<Tab.Screen name={homeName} component={HomeStack} />
<Tab.Screen name={settingsName} component={SignUpStack} />
</Tab.Navigator>
);
}
When using the same navigation method to direct to screens that are in the stack that I already am, it works fine. I hope someone can give me any pointers or help out! If you need any more info feel free to reach out!
PS: I'm very new to react-native so my apologies if I'm missing information.

I geas you are trying to navigate from stack navigator to tab navigator which is not ideal in react native you have to use nesting navigator
what I mean you have to use the tab navigator as a screen inside the stack navigator
this is React Navigation doc for nesting navigator https://reactnavigation.org/docs/nesting-navigators/

Related

Menu Button To Left Of Stack Navigator Back Button, headerBackVisible: true not working

I'm using a stack navigator nested in a drawer navigator for a react native app using react navigation 6. I'm only showing the header for the stack navigator. I want to put a hamburger menu button on the far left of the header, BUT I also want the default stack navigation back button to be present.
I found the setting headerBackVisible in the documentation, but haven't been able to find any examples of anyone using it, so I'm not sure if I'm using it properly. I'm trying to pass it as headerBackVisible: true in my screen options. No matter what I do, if I put anything else in headerLeft, I cannot get the header back button to show.
Anyone have any suggestions or examples on how to put something to the left of the header back button?
Yes, headerBackVisible is not working with headerLeft. As a workaround, you can import default back button (HeaderBackButton) from #react-navigation/stack and return it along with your hamburger component. Something like this:
import { createStackNavigator, HeaderBackButton } from '#react-navigation/stack';
<Stack.Navigator
screenOptions={({ navigation, route }) => ({
headerLeft: (props) => {
return (
<>
<Text>Menu</Text> // Replace with your hamburger component
{props.canGoBack && <HeaderBackButton {...props} />} // THIS IS WHAT YOU NEED
</>
);
},
})}> ....
<Stack.Screen ... />
<Stack.Screen ... />
</Stack.Navigator>
Snack link: https://snack.expo.dev/#rabiarashid/react-navigation---stack-navigator-example
Update (for react-navigation v6):
In v6, HeaderBackButton is moved to elements library i.e.
import { HeaderBackButton } from '#react-navigation/elements';
Ref: https://reactnavigation.org/docs/upgrading-from-5.x/#some-exports-are-now-moved-to-the-element-library

React Native goBack() with TabNavigator and StackNavigator react-navigation v5

Probably I am not doing well with react navigation and do not understand how nested navigation works.
I've got BottomTabNavigator with StackNavigator's in every component like in the example below.
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function AStack(props){
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen name="FirstScreenA" component={FirstScreenA}/>
<Stack.Screen
name="SecondScreenA"
component={SecondScreenA}
options={{
headerLeft: () => (
<TouchableOpacity
onPress={() => props.navigation.goBack()} >
</TouchableOpacity>/>
</Stack.Navigator>
<Tab.Navigator>
<Tab.Screen name="A" component={AStack} />
<Tab.Screen name="B" component={BStack} />
</Tab.Navigator>
Inside FirstScreenA component I have button which navigates to SecondScreenA.
And by props.navigaton.goBack() in Stack.Screen I want to go back to the FirstScreenA.
In fact, goBack() takes me to the previous screen in terms of Tab.Navigator. So, if I was in the BStack before, goBack() in the AStack moves me to screen in BStack.
My goal is to go back to the previous screen in AStack.
As far as I understand navigation prop from Tab.Navigator automatically goes to Stack Components. In this case I am not able to use anything like pop(), push(), popToTop() methods which should help, because those methods are not available in Tab.Navigator's navigation. Any hooks with StackActions does not work neither. navigation.navigate('FristScreenA') does not work, seems like it is think, that we already in the needed stack and screen, so nothing happens.
I guess there is a way to use internal navigation in Stack (not nested from Tab), but didn't find way to do that. If someone could clarify me and explain what to do - it would be great.
Thanks in advance.
This is because you are receiving props.navigation in the stack navigator component AStack, which is the direct children of your TabNavigator. In react navigation, children receive the props.navigation object of their containing parents, in your case, you're reciveing props.navigation object of the TabNavigator, that's why using goBack takes you to the previous Tab of your TabNavigator.
To receive navigation props of your stack navigator, you need to do that in your Stack.Screen components, in your case in FirstScreenA or SecondScreenA because they're the direct children of your StackNavigator. So using props.navigation.goBack in SecondScreenA component would actually take you back to FirstScreenA.

React Navigation: How to trigger navigation.push() in bottom tab navigator?

Here is what I am trying to do in my app with react navigation:
There is a default bottom tab navigator.
The app will listen to changes in the data.
If there is a change in the data for any of the screens in the bottom tab navigator, trigger navigation.push() to refresh the component.
What I observed is that the default behavior of the bottom tab navigator is navigation.navigate()...i.e. unless I reload the app, the screens do not refresh themselves.
In short, how do I trigger navigation.push() in the tab navigator? e.g. in the sample code below, how do I set the navigation behavior?
Thanks a lot in advance!
//How do I trigger navigation.push() when each of the bottom tab is pressed?
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
Pulled the following example from my code which solved the issue for me;
import { StackActions } from '#react-navigation/routers';
onPress={() => {
const pushAction =
StackActions.push('ProfileAnimal', { animal_id: item.id });
this.props.navigation.dispatch(pushAction);
this.props.navigation.navigate('ProfileAnimal', {animal_id: item.id});
};

Unable to Navigate to a StackNavigator nested in a DrawerNavigator

I started with a drawer navigation to allow me to pick a category page as a starting point. From each category page I want to create a stack navigator so that it navigates with a stack without each page displayed in the drawer. I started by adding a StackNavigator to the "product" page, but was told to move it to the app page and used a nest navigator. So far, this is what I have...
App.js ( Nested Navigators )
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="LoL"
drawerStyle={{
backgroundColor: "#212121",
}}
drawerContentOptions={{
activeTintColor: "orange",
inactiveTintColor: "white",
}}
>
<Drawer.Screen name="LoL" component={LoL} />
<Drawer.Screen name="CSGO" component={CSGO} />
<Drawer.Screen name="matchDetailsnav" component={matchDetailsNav} />
</Drawer.Navigator>
</NavigationContainer>
);
}
const matchDetailsNav = () => {
<Stack.Navigator>
<Stack.Screen name="MatchDetails" component={MatchDetails} />
</Stack.Navigator>
}
If we navigate to LoL.js we will see a list of cards to click on. I am using the following code to generate routes for each card.
{matches.map((match, index) => {
return (
<View>
<TouchableOpacity
key={index}
onPress={() => navigation.navigate('matchDetailsNav', match)}
>
<Card
.. passing some props here..></Card>
</TouchableOpacity>
</View>
This is where I started to get the following error...
The action 'NAVIGATE' with payload {** .. obj of the props im passing .. not important to question *} was not handled by any navigator.
Do you have a screen named 'MatchDetails?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
This was happening before I added the stack navigator but I am not sure why. I am importing the MatchDetails page into the App.js, there is not naming typo in my code, and I cannot seem to find why it doesn't see my match details page. Why is it not picking up my page?
EDIT: I just noticed that adding the nested navigator like I did in the example above put the name "matchDetailsNav" in my drawer nav as a clickable link, which is not what I want.
I simply want to gave a drawer nav and then have regular stack navigation for the pages/screens that link within the drawer nav. This way, clicking on a card living on a screen that is accesable from the Drawer Nav should use a stack nav ( allowing for the back button and sliding animation ).
I hope this edit clears up exactly what I am trying to do.

Navigate from a screen in one navigator to a screen in another navigator

I am using react-navigation v5.
In my app. I have two navigators, one stack navigator one drawer navigator:
const LoginStack = createStackNavigator();
const Drawer = createDrawerNavigator();
I show either one based on login status:
{state.loggedIn? (
<LoginStack.Navigator
...>
<LoginStack.Screen
name='login'
component={LoginScreen}
/>
<LoginStack.Screen
name='register'
component={RegisterScreen}
/>
</LoginStack.Navigator>
) : (
<>
<Drawer.Navigator
initialRouteName={Landing}
drawerContent={props => <MyDrawerContent {...props} />}
>
<Drawer.Screen name="landing" component={LandingScreen} />
...
</Drawer.Navigator>
</>
)}
As you can see above, if user is not logged in I show LoginStack navigator , otherwise I show Drawer navigator. And if you look closely in the Drawer.Navigator part, I have declared my own drawer content MyDrawerContent.
Inside MyDrawerContent, I have a logout button. I would like to navigate user to the LoginScreen of LoginStack. I tried :
<Button title="Logout" onPress={() => props.navigation.navigate('login')}/>
But I get error: The action 'NAVIGATE' with payload {"name":"Login"} was not handled by any navigator.. Is it because I am navigating to a screen of another navigator which MyDrawerContent doesn't belong to? How to resolve it?
Since you create two completely separate navigation trees, you cannot navigate between them because login screen is not registered, and thus not available, when you're in the Drawer.Navigator.
However, what you really want to do instead in your Logout button onPress, is change the loggedIn state to false. That will re-render the main app component and render the LoginStack instead. It's not very clear how you pass the state down the component tree so I can't provide a specific code example but hopefully you get the idea.