React Native: where to place Navigators for other screens? - react-native

My Application has a BottomTabNavigator, each Tab is linked to a component, which is a StackNavigator.
With that implementation, I can easily switch between the tab screens and also see a detailed screen.
Here is the code of my Screen component:
export default function Screen ({props, children}) {
return (
<>
<Stack.Navigator
screenOptions={{
cardShadowEnabled: false,
header: (props) => {
return <Header {...props} />
},
}}
>
<Stack.Screen name="Settings" component={SettingsScreen} />
</Stack.Navigator>
<SafeAreaView style={styles.screen}>
<View style={styles.container}>{ children }</View>
</SafeAreaView>
<TabNavigator i18n={i18n}/>
</>
);
}
In the header component, I have an Icon, which onPress needs to navigate to the SettingsScreen.
I am afraid that I am not sure if this is the right implementation of the SettingsNavigator and if yes, how is possible on click on my header menu to navigate to the SettingsScreen.
Here is my Header.js code:
export default function Header (props, navigation) {
...
return (
<View style={styles.container}>
<View style={styles.link} onPress={navigation.navigate("Settings")}>
<MaterialCommunityIcons name="tune" size={32} />
</View>
</View>
)
};
I get an error:
TypeError: navigation.navigate is not a function.(In
'navigation.navigate("Settings")', 'navigation.navigate' is undefined)
How can I access the navigation from my Header component?

I don't think it's a correct implementation.
Please try like following
<Stack.Navigator
initialRouteName={Routes.SignIn}
screenOptions={{
cardShadowEnabled: false,
header: (props) => {
return <Header {...props} />
},
}}
>
<Stack.Screen name={Routes.SignIn} component={SignInScreen} />
<Stack.Screen name={Routes.ForgotPassword} component={ForgotPasswordScreen} />
<Stack.Screen name={Routes.SignUp} component={SignUpScreen} />
</Stack.Navigator>

Related

How to set action on drawer menu icon while drawer is nested in stack navigation in react native?

I'd created a stack navigation & drawer navigation. The drawer navigation is nested in stack navigation because at first when user opens app for first time then they will see the walkthrough pages and then comes home page which is contains drawer navigation.
Here is the issue, I added image in headerLeft in screenOptions in Drawer.Navigator and on click on it called navigation.openDrawer() but appears that navigation.openDrawer is not a function.
All I want is that, I want to add images in header like as menu for open drawer & other 2 images for goes to other pages and the app logo in center.
below is the code & expo link for full view example:
**APP.JS**
if(isFirstTimeLoad) return (
<>
<StatusBar />
<Walkthrough onDone={handleDone} />
</>
);
if(!isFirstTimeLoad) return (
<NavigationContainer>
<MainNavigator />
</NavigationContainer>
)
**MAINNAVIGATOR.JS**
<Stack.Navigator>
<Stack.Screen name="Home" component={DrawerNavigator} />
</Stack.Navigator>
**DRAWERNAVIGATOR.JS**
<Drawer.Navigator
useLegacyImplementation
screenOptions={{
headerLeft: () => (
<TouchableOpacity onPress={openDrawer}>
<Image
source={require('../assets/menu.png')}
style={{ height: 20, width: 20 }}
/>
</TouchableOpacity>
),
}}>
<Drawer.Screen name="Feed" component={Feed} options={{}} />
<Drawer.Screen name="Article" component={Article} />
</Drawer.Navigator>
here is the full source code for convinience, expo link : click here
import { useNavigation,DrawerActions } from '#react-navigation/native';
export default function DrawerNavigator(props) {
// const {navigation} = props
const navigation = useNavigation();
const openDrawer = () => navigation.dispatch(DrawerActions.openDrawer());
return (
<Drawer.Navigator
useLegacyImplementation
screenOptions={{
headerLeft: () => (
<TouchableOpacity onPress={openDrawer}>
<Image
source={require('../assets/menu.png')}
style={{ height: 20, width: 20 }}
/>
</TouchableOpacity>
),
}}>
<Drawer.Screen name="Feed" component={Feed} options={{}} />
<Drawer.Screen name="Article" component={Article} />
</Drawer.Navigator>
);
}
https://snack.expo.dev/hyt2VDjqB
Try this please :) this works
Hope it helps,feel free for doubts

React Navigation Bottom Tabs Navigator plus Modal Screen

I have the following code to create a Tab using React Native Navigation v6.x:
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
The HomeScreen has a button which should call a Modal Screen.
My question is: How would I add this modal screen in my Navigator to call it from HomeScreen and how would be this call code?
Thanks!
You don't need to include the modal in the navigator to open it from the homepage.
You could do something like this:
const HomeScreen = () => {
const [modalVisible, setModalVisible] = useState(false);
function _myModal() {
return(
<Modal
animationType="slide"
visible={modalVisible}
onRequestClose={() => {setModalVisible(false)}}
>
<Text>Hello, I am a modal!</Text>
</Modal>
)
}
// your code
return (
<View>
{/*your code*/}
<Pressable
onPress={() => setModalVisible(true)}
>
<Text>Show Modal</Text>
</Pressable>
{_myModal()}
</View>
);
};
The React-Native documentation has an example for class component as well in case you're working with these, and more info that should help you as well.
If you want to open modal screen from your home page then you should create a home screen stack navigator and add two screen in that stack(home and modal screens), and then navigate to that modal by pressing button.
Tab Navigator(RootNavigation MyTabs)
...
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStack} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
Stack Navigator(HomeStack)
cosnt Stack = createStackNavigator();
function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="ModalScreen" component={ModalScreen}
options={{ presentation: 'modal' }} />
</Stack.Navigator>
);
}
HomeScreen
export default function HomeScreen({navigation}) {
return (
<View>
<TouchableOpacity onPress={() => navigation.navigate('ModalScreen'}>
<Text>Open ModalScreen</Text>
</TouchableOpacity>
</View>
)
}

React Native Open Drawer with Button

I have a Drawer Navigator with some Screens. One of the Screens is a TabNavigator. Now I want to implement a HamburgerMenu-Button to open the drawer in all of the Tab-Navigator Screens.
Where do I implement that Button? In the TabNavigator or its child Screens or in the Drawer Screens?
Here are a few Code Snippets:
DrawerNavigator:
export default class DrawerMenu extends React.Component {
render() {
return (
<Drawer.Navigator initialRouteName='Home'>
<Drawer.Screen name='Home' component={TabNavigator} />
<Drawer.Screen name='About Us' component={AboutUsScreen} />
<Drawer.Screen name='About the App' component={AboutTheAppScreen} />
<Drawer.Screen name='Impressum' component={ImpressumScreen} />
</Drawer.Navigator>
);
}
}
TabNavigator:
const Tab = createBottomTabNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator tabBar={(props) => <TabBar {...props}></TabBar>}>
<Tab.Screen
name='Tab1'
component={Tab1}
initialParams={{ icon: 'info' }}
></Tab.Screen>
<Tab.Screen
name='Tab2'
component={Tab2}
initialParams={{ icon: 'circle-o-notch' }}
></Tab.Screen>
<Tab.Screen
name='Tab3'
component={Tab3}
initialParams={{ icon: 'home' }}
></Tab.Screen>
<Tab.Screen
name='Tab4'
component={Tab4}
initialParams={{ icon: 'glass' }}
></Tab.Screen>
<Tab.Screen
name='Tab5'
component={Tab5}
initialParams={{ icon: 'road' }}
></Tab.Screen>
</Tab.Navigator>
);
};
single Screen in TabNavigator:
const Tab1 = () => {
return (
<View style={styles.container}>
<Text style={styles.text}>Tab1</Text>
</View>
);
};
Any help is appreciated.
In the end it was an easy answer. We just had to give through the props. (I think)
single Screen in TabNavigator:
const Tab1 = ({navigation}) => {
return (
<View style={styles.container}>
<Text style={styles.text}>Tab1</Text>
</View>
);
};
That way we could easily use the navigation.openDrawer function in an onPress event.

Open a new screen through a tab screen

I'm trying to show a single screen when someone clicks on a text.
I created a login screen, a single screen called Test, and the main screen with a navigation container that contains two screens inside. And I would like to put inside one of the screens, a clickable text that opens a new screen when clicked.
I'm passing the navigator as a parameter too, but when I try to run my app and I click at the clickable text, I receive this message:
The action 'NAVIGATE' with payload {"name":"Test"} was not handled by
any navigator.
Do you have a screen named 'Test'?
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 is a development-only warning and won't be shown in production.
My routes file:
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='Login' screenOptions={{headerShown: false}}>
<Stack.Screen name='Main' component={Main} />
<Stack.Screen name='Login' component={Login} />
<Stack.Screen name='Test' component={Test} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
Tab Navigator file
const Tab = createBottomTabNavigator();
export default function App ({navigation}){
return (
<NavigationContainer independent={true} >
<Tab.Navigator>
<Tab.Screen
name="Profile"
component={ProfileScreen}
options={{
tabBarLabel: 'Perfil',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home-outline" color={color} size={size} />
),
}}
/>
<Tab.Screen
name="List"
component={ListScreen}
initialParams={{ navigation: navigation }}
options={{
tabBarLabel: 'List'
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
ListScreen function (contains the screen that shows a clickable text)
function ListScreen(param) {
return (
<SafeAreaView style={{ flex: 1, backgroundColor: "#fff" }}>
<LinearGradient
colors={['#000f17', '#0c3552']}
style={styles.main_container}>
<SafeAreaView style={styles.main_subcontainer}>
<List navigate={param}/>
</SafeAreaView>
</LinearGradient>
</SafeAreaView>
);
}
List component
export class List extends Component {
constructor(props) {
super(props);
console.log(this.props.navigate.navigation.navigate);
}
render() {
return (
<View>
<ScrollView>
<TouchableOpacity onPress={() => {
this.props.navigate.navigation.navigate('Test')
}}>
<Text>Click Here</Text>
</TouchableOpacity>
</ScrollView>
</View>
);
}
}

buttons not displaying in expo react navigation header

I was following this tutorial to learn react navigation in expo. in this header when i give button it is not getting displayed in the header. code below
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Homecomponent}
options={{
headerTitle: ()=> <Icon name="home" />,
headerRight: () => (
<Button
onPress={() => alert("This is a button!")}
title="Info"
color="#00cc00"
/>
)
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
The headerRight button is not getting displayed.
TIA
import { HeaderBackButton } from 'react-navigation-stack';
//import Ionicons from 'react-native-vector-icons/MaterialIcons';// add if you have this
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Homecomponent}
options={{
headerTitle: ()=> <Icon name="home" />,
headerRight: () => (
<HeaderBackButton
onPress={() => alert("This is a button!")}
//title="Info"
color="#00cc00"
/>
// Here you can add your icon to show info sample code for icon is
// <Icon name="info" size={25}/>
)
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
try this code may be helpful for you