onPress to navigate on a screen not navigating - react-native

I am a beginner in React Native and I would like to navigate on a screen when I press the Button of my Navigator screen but it's not working.
Because when I press the Button in TabOneStack.Screen nothing is happening I don't understand, I would like to navigate to TabTwoScreen. I use React Navigation 5.6.1.
const BottomTab = createBottomTabNavigator<BottomTabParamList>();
export default function BottomTabNavigator() {
return (
<BottomTab.Navigator
initialRouteName="TabOne">
<BottomTab.Screen
name="TabOne"
component={TabOneNavigator}
/>
<BottomTab.Screen
name="TabTwo"
component={TabTwoNavigator}
options={{
tabBarLabel: 'Autour de moi',
tabBarIcon: ({ color }) => <TabBarIcon name="ios-navigate" color={color} />,
}}
/>
</BottomTab.Navigator>
);
}
const TabOneStack = createStackNavigator<TabOneParamList>();
function TabOneNavigator() {
return (
<TabOneStack.Navigator>
<TabOneStack.Screen
name="TabOneScreen"
component={TabOneScreen}
options={({ navigation }) => ({
headerTitle: 'Rejoindre', headerRight: () => (
<Button onPress={() => navigation.navigate('TabTwoScreen')}
icon={
<Icon
name='ios-log-in'
type='ionicon'
size={15}
color="white"
/>
}
/>
),
})}
/>
</TabOneStack.Navigator>
);
}
const TabTwoStack = createStackNavigator<TabTwoParamList>();
function TabTwoNavigator() {
return (
<TabTwoStack.Navigator>
<TabTwoStack.Screen
name="TabTwoScreen"
component={TabTwoScreen}
options={{ headerTitle: 'Autour de moi' }}
/>
</TabTwoStack.Navigator>
);
}
Why when I press the Button in TabOneStack.Screen nothing is happening?
Thank you in advance

You need to use props for navigation and you can try this
options={({ navigation }) => ({
headerTitle: 'Rejoindre', headerRight: props => (
<Button onPress={() => props.navigation.navigate('TabTwoScreen')}

Related

React-Native, Navigation, Drawers and passing inline functions with props

I have a Drawer Navigator nested inside a Stack navigator. It all works fine but I get the following warning:-
Looks like you're passing an inline function for 'component' prop for the screen 'Home' (e.g. component={() => }). Passing an inline function will cause the component state to be lost on re-render and cause perf issues since it's re-created every render. You can pass the function as children to 'Screen' instead to achieve the desired behaviour.
Here is the code.
const [isAuthenticated, setIsAuthenticated] = React.useState(false);
const [initialRoute, setInitialRoute] = React.useState("");
const handleSignOut = () => {
// TODO implement sign out mechanism
};
return (
<NavigationContainer>{
<Stack.Navigator initialRouteName="Sign In" >
{isAuthenticated ? (
<Stack.Screen name="Home"
component={() => <HomeDrawer initialRoute={initialRoute} handleSignOut={handleSignOut}/>}
options={({ route, navigation }) => ({
headerTitle: getFocusedRouteNameFromRoute(route),
headerLeft: () => (
<Button
title="Menu"
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
),
headerRight: () => (
<Button onPress={handleSignOut} title="Sign Out" />
),
})}
/>
) : (
...
I fixed the warning by moving the component, but now the Drawer has stop working completely and I get this error:-
The action 'TOGGLE_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
Here is the new code.
const [isAuthenticated, setIsAuthenticated] = React.useState(false);
const [initialRoute, setInitialRoute] = React.useState("");
const handleSignOut = () => {
// TODO implement sign out mechanism
};
const Draw = () => {<HomeDrawer initialRoute={initialRoute} handleSignOut={handleSignOut}/>};
return (
<NavigationContainer>{
<Stack.Navigator initialRouteName="Sign In" >
{isAuthenticated ? (
<Stack.Screen name="Home"
component={Draw}
options={({ route, navigation }) => ({
headerTitle: getFocusedRouteNameFromRoute(route),
headerLeft: () => (
<Button
title="Menu"
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
),
headerRight: () => (
<Button onPress={handleSignOut} title="Sign Out" />
),
})}
/>
) : (
...
I'm new to React-Native and on a steep learning curve. I've read a bunch of tutorials but stumped on this one. I can see I need to pass initialRoute at least, but not sure how to do that. A fix with an explanation would be great.
I found the answer in the end. It was pretty straight forward, but not when there are so many things to learn at once :-) When I moved the component like so it all worked.
<Stack.Screen name="Home"
options={({ route, navigation }) => ({
headerTitle: getFocusedRouteNameFromRoute(route),
headerLeft: () => (
<Button
title="Menu"
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
),
headerRight: () => (
<Button onPress={handleSignOut} title="Sign Out" />
),
})}
>
{(props) => (
<HomeDrawer {...props} initialRoute={initialRoute} handleSignOut={handleSignOut} />
)}
</Stack.Screen>
<Stack.Screen name="TEST" component={TestScreen}
screenOptions={{ headerShown: true }}
options={{ headerTitle: "Hello" }}
/>

React-navigation default drawer icon, how to change it?

How can I change the icon point in the image below? I have not been able to find the documentation in the docs, I would like to change it to a different icon but I have no idea how to do this.
I found documentation about drawerIcon but as far as I know and manage to implement that icon is for the menu items in the drawer it self not for the screen header.
Here is my code:
const Drawer = createDrawerNavigator();
const headerOptions = {
title: 'Task List',
drawerIcon: ({ focused, size, color }) => <Ionicons name="ios-pizza" color="red" size={24} />,
};
const HomeScreen = ({ navigation }, props) => {
return (
<Drawer.Navigator screenOptions={{ drawerType: 'front' }}>
<Drawer.Screen name="TaskList" component={TaskListScreen} options={headerOptions} />
<Drawer.Screen name="TaskView" component={TaskViewScreen} />
<Drawer.Screen name="Notifications" component={Notifications} />
<Drawer.Screen name="Login" component={LoginScreen} />
</Drawer.Navigator>
);
};
But as mention before it renders the icons in the drawer item as shown below
headerLeft: Function which returns a React Element to display on the left side of the header. You can use it to implement your custom left button, for example:
<Drawer.Navigator
screenOptions={({ navigation }) => ({
headerLeft: props => <IconComponent onPress={navigation.toggleDrawer} />,
})}
>
...
</Drawer.Navigator>
<Drawer.Navigator
screenOptions={{
headerTintColor: 'red', // -----> by changing color from here
}} drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen />
</Drawer.Navigator >
you can also use a image as a drawer icon.
screenOptions={({ navigation }) => ({
headerLeft: () =>
<Pressable onPress={navigation.toggleDrawer}>
<Text>
<Avatar.Image size={32} source={{ uri: deafaultImage }} />
</Text>
</Pressable >
})}

React native bottom tab navigate to desire screen

First I create Bottomtabs and import in Core navigator;
const BottomTabs = createBottomTabNavigator();
function BottomTabNavigator({ navigation, route }) {
return (
<BottomTabs.Navigator>
<BottomTabs.Screen
name="ExploreTab"
component={ExploreNavigator}
/>
<BottomTabs.Screen
name="FormScreen"
component={ProfileNavigator}
options={({ navigation }) => ({
tabBarLabel: "",
tabBarButton: (props) => (
<TouchableOpacity
{...props}
onPress={() => {
console.log({ navigation });
navigation.navigate("FormScreen");
}}
>
<View>
<Icon
type="font-awesome-5"
name="plus"
size={moderateScale(25)}
color={Colors.white}
/>
</View>
</TouchableOpacity>
),
})}
/>
<BottomTabs.Screen
name="ProfileTab"
component={ProfileNavigator}
/>
</BottomTabs.Navigator>
);
}
export default BottomTabNavigator;
The bottom tab navigator is part of the core navigator and the core navigator is the app-level navigator.
function CoreNavigator() {
return (
<CoreStack.Navigator>
<CoreStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
options={{
headerShown: false,
}}
/>
<CoreStack.Screen name="AboutScreen" component={AboutScreen} />
<CoreStack.Screen name="WebScreen" component={WebScreen} />
</CoreStack.Navigator>
);
}
when I click on the bottom tab middle plus button. It should navigate to the form screen FormScreen.
Check image
In simple words below code not working which is present at the Botton tab navigator.
when I click on the bottom plus button Bellow app navigates to ProfileNavigators default screen. I want the app to navigate to FormScreen.
<BottomTabs.Screen
name="FormScreen"
component={ProfileNavigator}
options={({ navigation }) => ({
tabBarLabel: "",
tabBarButton: (props) => (
<TouchableOpacity
{...props}
onPress={() => {
console.log({ navigation });
navigation.navigate("FormScreen");
}}
>
<View>
<Icon
type="font-awesome-5"
name="plus"
size={moderateScale(25)}
color={Colors.white}
/>
</View>
</TouchableOpacity>
),
})}
/>
Try to use:
navigation.reset({
index: 0,
routes: [{ name: 'FormScreen' }],
});
Instead of navigation.navigate("FormScreen");

opening drawer by pressing on bottom tab not working

I am trying to toggleDrawer on TabPress in BottomTab, but when I press on tab I get the following error navigation.toggleDrwer() is not a function.
This is my code:
export default function BottomTab() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={DrawerTab} style={styles} listeners={({ navigation }) => ({
tabPress: e => {
e.preventDefault()
navigation.toggleDrawer()
},
})} />
</Tab.Navigator>
</NavigationContainer>
);
}
i have manage to find the answer. So you actually have to use dispatch.
<Tab.Screen name="Home" component={DrawerTab} style={styles} listeners={({ navigation }) => ({
tabPress: e => {
e.preventDefault()
navigation.dispatch(DrawerActions.toggleDrawer())
},
})} />

react-navigation: Navigate to a different screen from a button in header

I have a Icon on the right side of my header and on press of that button i want to navigate to a different screen.
I have searched very much for this but all of the solutions are for class components and there are no official documentation available for it.
I am using react native version 0.61.4.
On press of the icon in the header on the right i want to move the 'ProfileScreen'. All the other navigation is working fine. I have a button in 'HomeScreen' to move to 'ResultsScreen' but cannot go to 'ProfileScreen' from the header.
Here is snippet of my code
const Stack = createStackNavigator();
const App = () => {
return (
<SafeAreaView style={{ flex: 1 }}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={
{
title: 'Home',
headerStyle: {
backgroundColor: '#273469',
},
headerTintColor: '#EBF2FA',
headerRight: () => (
<Icon
onPress={() => navigate('ProfileScreen')}
name="edit"
type="material"
/>
),
}
}
/>
<Stack.Screen
name="ResultsScreen"
component={ResultsScreen}
/>
<Stack.Screen
name="ProfileScreen"
component={ProfileScreen}
/>
</Stack.Navigator>
</NavigationContainer>
</SafeAreaView>
)
}
options can take a function as an argument and this function takes props as a parameter.
Here is the documentation
Here is the TypeScript definition for information:
* Navigator options for this screen.
*/
options?: ScreenOptions | ((props: {
route: RouteProp<ParamList, RouteName>;
navigation: any;
}) => ScreenOptions);
as you can see props, contain the navigation object that you can use to call navigate like this :
options={({ navigation }) => ({
title: 'Home',
headerStyle: {
backgroundColor: '#273469',
},
headerTintColor: '#EBF2FA',
headerRight: () => (
<Icon
onPress={() => navigation.navigate('ProfileScreen')}
name="edit"
type="material"
/>
),
})}
Adding to Kevin's answer, you can also add a simple button in the header:
options={({ navigation }) => ({
title: 'Home',
headerStyle: {
backgroundColor: '#273469',
},
headerTintColor: '#EBF2FA',
headerRight: () => (
<Button // a button in the header!
onPress={() =>
navigation.navigate('Account')}
title="Account"
/>
),
})}
Here is what worked for me:
<Stack.screen
name="YourScreenName"
headerShown=true
options={({ navigation }) => ({
title: 'YourOtherScreenName',
headerRight: () => (
<TouchableOpacity
onPress={() => navigation.dispatch(StackActions.push('articleEdit', {articleId: 'new'}))} >
<View style={SomeStyleWithPaddingYouLike}>
<JSX_That_Renders_Your_Icon />
</View>
</TouchableOpacity>
),
})}
/>