anonymus_rex
anonymus_rex

Reputation: 579

Navigate to other StackNavigator screen when press button on navbar

I'm pretty new to react and this is my first app.

I have a stack navigator with 2 screens by now: MainMenu and Profile. While the user is in MainMenu, a button on top right corner is shown and I need to redirect the user to the Profile screen when this button is pressed. I need something like this.props.navigation.navigate('Profile') but this does not work, because this, props and navigation are not defined.

My thinks are that I cannot redirect to Profile from this stack navbar, cause Profile is still defined yet, but I don't know another way to do it.

enter image description here

// mainStack.js
import React from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';
import { createStackNavigator } from '@react-navigation/stack';
import MainMenu from '../../screens/home/mainMenu';
import Profile from '../../containers/profileContainer';
import Icon from 'react-native-vector-icons/FontAwesome';
import { useSelector } from 'react-redux';


const MainStack = () => {
    const Stack = createStackNavigator();
    const isAdmin = (useSelector(state => state.auth.user.role) === 'admin');

    function renderUserMenu() {
        return (
            <TouchableOpacity style={{ marginRight: 20 }} onPress={() => console.log("HERE I NEED TO REDIRECT TO THE SCREEN PROFILE") } >
                <Icon style={{ color: 'white' }} name='user-circle-o' size={30} />
            </TouchableOpacity>
        )
    }

    function LogoTitle() {
        return (
            <Image
                style={{ width: 150, height: 50 }}
                source={require('../../assets/logo-with-slogan.png')}
            />
        );
    }

    function renderConfigBtn(_isAdmin) {
        if (!_isAdmin) {
            return (
                <TouchableOpacity style={{ marginRight: 10 }} onPress={() => console.log('Configuraciones')} >
                    <Icon style={{ color: 'white' }} name='cog' size={30} />
                </TouchableOpacity>
            )
        }
    }

    return (
        <Stack.Navigator>
            <Stack.Screen
                name="MainMenu"
                component={MainMenu}
                options={{
                    headerTitle: props => <LogoTitle {...props} />,
                    headerRight: () => (
                        <View style={{ flexDirection: 'row' }}>
                            {renderConfigBtn(isAdmin)}
                            {renderUserMenu()}
                        </View>
                    ),
                    headerStyle: { backgroundColor: '#0064c8' },
                }}
            />
            <Stack.Screen
                name="Profile"
                component={Profile}
                options={{
                    headerStyle: { backgroundColor: '#0064c8' },
                }}
            />
        </Stack.Navigator>
    )
}

export default MainStack;

Also, this stack is inside a navigation container as follows:

import React from 'react';
import { useSelector } from "react-redux";
import { NavigationContainer } from "@react-navigation/native";

import AuthStack from "./authStack";
import MainStack from "./mainStack";

const AppNavigator = props => {
    const isAuth = useSelector(state => !!state.auth.access_token);

    return (
        <NavigationContainer>
            { !isAuth && <AuthStack/>}
            { isAuth && <MainStack/>}
        </NavigationContainer>
    );
};

export default AppNavigator;

I would appreciate any help.

Upvotes: 0

Views: 2467

Answers (3)

Jignesh Mayani
Jignesh Mayani

Reputation: 7193

We simply can import the useNavigation hook from the react-navigation/native package and can implement navigation with the use of this hook without accessing the navigation props from the component.

For Ex.

First import the hook,

import { useNavigation } from '@react-navigation/native';

Use the hook to implement navigation as below in MainStack.js:

const navigation = useNavigation();

function renderUserMenu() {
    return (
        <TouchableOpacity style={{ marginRight: 20 }} onPress={() => navigation.navigate("Profile") } >
            <Icon style={{ color: 'white' }} name='user-circle-o' size={30} />
        </TouchableOpacity>
    )
}

Upvotes: 0

Birender Pathania
Birender Pathania

Reputation: 494

Use navigation options and then pass it to the function to navigate to profile:

  <Stack.Screen
            name="MainMenu"
            component={MainMenu}
            options={({ navigation }) => ({ ......

Upvotes: 2

Guruparan Giritharan
Guruparan Giritharan

Reputation: 16334

You can access 'navigation' in options like below

   options={({navigation})=>({
                    headerTitle: props => <LogoTitle {...props} />,
                    headerRight: () => (
                        <View style={{ flexDirection: 'row' }}>
                            {renderConfigBtn(isAdmin,navigation)}
                            {renderUserMenu(navigation)}
                        </View>
                    ),
                    headerStyle: { backgroundColor: '#0064c8' },
                })}

Basically you can pass a function as a prop to options and navigation will be passed to it as a parameter.

function renderUserMenu(navigation) {
        return (
            <TouchableOpacity style={{ marginRight: 20 }} onPress={() => navigation.navigate('YOUR SCREEN') } >
                <Icon style={{ color: 'white' }} name='user-circle-o' size={30} />
            </TouchableOpacity>
        )
}

And you can change the renderUserMenu function like above so that it will do the navigation as required.

Upvotes: 2

Related Questions