Navigate to other StackNavigator screen when press button on navbar - react-native

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.
// 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.

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.

Use navigation options and then pass it to the function to navigate to profile:
<Stack.Screen
name="MainMenu"
component={MainMenu}
options={({ navigation }) => ({ ......

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>
)
}

Related

React component retains previous state

I've been learning React and React Native for less than a week, so there are concepts that I'm still learning.
The code below is a first attempt to code an app with navigation through a bottom tab navigator, more specifically using #react-navigation/material-bottom-tabs and react-native-paper. There are 3 screens called Home, Details and Help. Home and Details both contain a button "ask for help", which will both redirect to the Help screen with a special message that is passed as parameter. For example:
<Button
icon="camera"
mode="contained"
onPress={() => navigation.navigate("Help", { txt: "Everything is OK!" })}
style={{ marginTop: 16 }}
>
Ask for help
</Button>
When loading the application, HelpScreen is initiated with initialParams={{ txt: "nothing" }} and the screen will display You said nothing.
From HomeScreen, clicking on the button redirects me to HelpScreen with onPress={() => navigation.navigate("Help", { txt: "Everything is OK!" })}. Therefore the screen will display You said Everything is OK!.
When moving to another screen and then going back to HelpScreen with the use of the bottom tabs, I expect HelpScreen to be re-rendered with its original value. Therefore I expect the screen to say You said nothing. But no, it still says You said Everything is OK!. The same behavious happens with DetailsScreen with another text.
In the HelpScreen function, I am not saving the parameter to a state. So I don't expect the component to retain the previous value when re-rendering. So why doesn't the component reset to its original value when re-rendering?
Or is it not re-rendering? In which case can you please explain why?
Here is the code:
import { registerRootComponent } from "expo";
import { NavigationContainer } from "#react-navigation/native";
import { NativeStackScreenProps } from "#react-navigation/native-stack";
import { createMaterialBottomTabNavigator } from "#react-navigation/material-bottom-tabs";
import { View } from "react-native";
import { Button, Text } from "react-native-paper";
import { SafeAreaProvider } from "react-native-safe-area-context";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
type NavigationParamList = {
Home: undefined;
Details: undefined;
Help: { txt: string };
};
type PropsHome = NativeStackScreenProps<NavigationParamList, "Home">;
type PropsDetails = NativeStackScreenProps<NavigationParamList, "Details">;
type PropsHelp = NativeStackScreenProps<NavigationParamList, "Help">;
const Tab = createMaterialBottomTabNavigator<NavigationParamList>();
function HomeScreen({ navigation, route }: PropsHome) {
console.log("HOME");
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Button
icon="camera"
mode="contained"
onPress={() =>
navigation.navigate("Help", { txt: "Everything is OK!" })
}
style={{ marginTop: 16 }}
>
Ask for help
</Button>
</View>
);
}
function DetailsScreen({ navigation, route }: PropsDetails) {
console.log("DETAILS");
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Button
icon="camera"
mode="contained"
onPress={() => navigation.navigate("Help", { txt: "HELP ME!" })}
style={{ marginTop: 16 }}
>
Ask for help
</Button>
</View>
);
}
function HelpScreen({ route }: PropsHelp) {
console.log("HELP");
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Text>You said {route.params.txt}</Text>
</View>
);
}
export default function App() {
return (
<SafeAreaProvider>
<NavigationContainer>
<Tab.Navigator initialRouteName="Home" screenOptions={{}}>
<Tab.Screen
name="Home"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}}
component={HomeScreen}
/>
<Tab.Screen
name="Details"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons
name="alien-outline"
color={color}
size={26}
/>
),
}}
component={DetailsScreen}
/>
<Tab.Screen
name="Help"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons
name="chat-question-outline"
color={color}
size={26}
/>
),
}}
component={HelpScreen}
initialParams={{ txt: "nothing" }}
/>
</Tab.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
}
registerRootComponent(App);
Note that I have not used the useState hook. I understand that this hook would be needed when one wants the retain a value, not reset it.
React Navigation avoids rerendering each screen every time is focused for both better user experience and avoiding unnecessary screen rerendering.
You should override this default behavior and detect when the screen is revisited/focuses and rerender that screen.
It provided utility hooks to listen to the screen is focused - https://reactnavigation.org/docs/function-after-focusing-screen/
Here code refactor with a solution:
import { registerRootComponent } from "expo";
import {useEffect,useState} from "react"
import { NavigationContainer ,useIsFocused} from "#react-navigation/native";
import { NativeStackScreenProps } from "#react-navigation/native-stack";
import { createMaterialBottomTabNavigator } from "#react-navigation/material-bottom-tabs";
import { View } from "react-native";
import { Button, Text } from "react-native-paper";
import { SafeAreaProvider } from "react-native-safe-area-context";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
type NavigationParamList = {
Home: undefined;
Details: undefined;
Help: { txt: string };
};
type PropsHome = NativeStackScreenProps<NavigationParamList, "Home">;
type PropsDetails = NativeStackScreenProps<NavigationParamList, "Details">;
type PropsHelp = NativeStackScreenProps<NavigationParamList, "Help">;
const Tab = createMaterialBottomTabNavigator();
function HomeScreen({ navigation, route }: PropsHome) {
console.log("HOME");
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Button
icon="camera"
mode="contained"
onPress={() =>
navigation.navigate("Help", { txt: "Everything is OK!" })
}
style={{ marginTop: 16 }}
>
Ask for help
</Button>
</View>
);
}
function DetailsScreen({ navigation, route }: PropsDetails) {
console.log("DETAILS");
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Button
icon="camera"
mode="contained"
onPress={() => navigation.navigate("Help", { txt: "HELP ME!" })}
style={{ marginTop: 16 }}
>
Ask for help
</Button>
</View>
);
}
function HelpScreen({ route ,navigation}: PropsHelp) {
const [message,setMessage] = useState("")
const isFocused = useIsFocused()
useEffect(()=>{
setMessage(route.params.txt)
return ()=>{
navigation.setParams({txt:"nothing"})
}
},[isFocused])
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Route name: {route.name}</Text>
<Text>You said {message}</Text>
</View>
);
}
export default function App() {
return (
<SafeAreaProvider>
<NavigationContainer>
<Tab.Navigator initialRouteName="Home" screenOptions={{}}>
<Tab.Screen
name="Home"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}}
component={HomeScreen}
/>
<Tab.Screen
name="Details"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons
name="alien-outline"
color={color}
size={26}
/>
),
}}
component={DetailsScreen}
/>
<Tab.Screen
name="Help"
options={{
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons
name="chat-question-outline"
color={color}
size={26}
/>
),
}}
component={HelpScreen}
initialParams={{ txt: "nothing" }}
/>
</Tab.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
}
Working Demo - https://snack.expo.dev/#emmbyiringiro/493761

React native (React navigation)- instance of same screen in differents tabs. Navigate from drawer

I have an issue with react navigation.
I would like to have the same behavior as the linkedIn app has.
I mean, in that app, you can open the settings page from the drawer in differents tabs. You can open it from the first tab, second one... and so on. and at the end you get multiple instances.
I am not able to reproduce this behavior
My navigation is:
One drawer with one drawer screen (one Tab navigator inside). 3 tabs screens inside that Tab navigator. Each one contains a stack. I have set the same screens in that screen. For example I want to share the Profile, so I have one profile screen in each tab.
In the customDrawer I navigate to screens name, but here is the problem. React navigation does not know what stack should call before calling the right screen.
And I cannot find a way to know the current mounted stack so I cannot set it dinamically in order to do inside the custom drawer:
onPress={() =>
props.navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.SETTINGS })
}
Thanks!
App.tsx
/* eslint-disable react-native/no-inline-styles */
import 'react-native-gesture-handler';
import React from 'react';
import { Text } from 'react-native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
} from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { QueryClient, QueryClientProvider } from '#tanstack/react-query';
import { StatusBar } from 'expo-status-bar';
import HomeStackScreen from '#pages/Home';
import { Routes } from '#src/constants/routes';
import { PracticalStackScreen } from '#src/pages/Practical/Practical';
import { TheoryStackScreen } from '#src/pages/Theory/Theory';
// Create a client
const queryClient = new QueryClient();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator
screenOptions={{ headerShown: false }}
initialRouteName={Routes.student.home.STACK}
>
<Tab.Screen
name={Routes.student.theory.STACK}
component={TheoryStackScreen}
options={{ title: 'TEÓRICO' }}
/>
<Tab.Screen
name={Routes.student.home.STACK}
component={HomeStackScreen}
options={{ title: '' }}
/>
<Tab.Screen
name={Routes.student.practical.STACK}
component={PracticalStackScreen}
options={{ title: 'PRÁCTICO' }}
/>
</Tab.Navigator>
);
};
function CustomDrawerContent(props: any) {
console.log('props ', props);
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(Routes.student.SETTINGS)}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(Routes.student.PAYMENT)}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(Routes.student.PROFILE)}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(Routes.student.FAQ)}
/>
<DrawerItem
label='Atención al alumno'
onPress={() => props.navigation.navigate(Routes.student.STUDENT_SUPPORT)}
/>
</DrawerContentScrollView>
);
}
const DrawerNavigation = () => {
return (
<Drawer.Navigator
useLegacyImplementation={true}
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName={Routes.student.home.STACK}
>
<Drawer.Screen name={Routes.MAIN_TAB} component={TabNavigator} />
</Drawer.Navigator>
);
};
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<StatusBar />
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
</QueryClientProvider>
);
}
Home.tsx
/* eslint-disable react-native/no-color-literals */
import React from 'react';
import { StyleSheet, Text, View, Pressable } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const HomeStack = createNativeStackNavigator();
export const HomeStackScreen = (): JSX.Element => {
return (
<HomeStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<HomeStack.Screen name={Routes.student.home.MAIN} component={Home} />
<HomeStack.Screen name={Routes.student.PROFILE} component={Profile} />
<HomeStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<HomeStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<HomeStack.Screen name={Routes.student.FAQ} component={Faq} />
<HomeStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</HomeStack.Navigator>
);
};
export const Home = ({ navigation }: any): JSX.Element => (
<View style={styles.container}>
<Text>Home Screen</Text>
<Pressable style={styles.button} onPress={() => navigation.navigate(Routes.student.PROFILE)}>
<Text style={styles.text}>Perfil</Text>
</Pressable>
</View>
);
const backgroundColor = '#fff';
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: 'grey',
borderRadius: 4,
elevation: 3,
justifyContent: 'center',
paddingHorizontal: 32,
paddingVertical: 12,
},
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
text: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
letterSpacing: 0.25,
lineHeight: 21,
},
});
Theroy.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const TheoryStack = createNativeStackNavigator();
export const TheoryStackScreen = (): JSX.Element => {
return (
<TheoryStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<TheoryStack.Screen name={Routes.student.theory.MAIN} component={Theory} />
<TheoryStack.Screen name={Routes.student.PROFILE} component={Profile} />
<TheoryStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<TheoryStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<TheoryStack.Screen name={Routes.student.FAQ} component={Faq} />
<TheoryStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</TheoryStack.Navigator>
);
};
export function Theory({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Theory Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Practical'
onPress={() => navigation.navigate(Routes.student.practical.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Practical.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const PracticalStack = createNativeStackNavigator();
export const PracticalStackScreen = (): JSX.Element => {
return (
<PracticalStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<PracticalStack.Screen name={Routes.student.practical.MAIN} component={Practical} />
<PracticalStack.Screen name={Routes.student.PROFILE} component={Profile} />
<PracticalStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<PracticalStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<PracticalStack.Screen name={Routes.student.FAQ} component={Faq} />
<PracticalStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</PracticalStack.Navigator>
);
};
export function Practical({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Practical Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Theory'
onPress={() => navigation.navigate(Routes.student.theory.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Try renaming your Settings screen component differently for each stack navigator. So something like
<PracticalStack.Screen name="Practical/Settings" component={Settings} />
<HomeStack.Screen name="Home/Settings" component={Settings} />
Then you could navigate to the appropriate screen from your drawer based on the tab in focus.
I think I found a possible solution to my question. I have changed the CustomDrawerContent.
function CustomDrawerContent(props: any) {
const drawerState = props.state.routes[0]?.state;
const routeIndex = drawerState?.index;
const focusedTab = drawerState?.routes?.[routeIndex]?.name || Routes.student.home.STACK;
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.SETTINGS })}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PAYMENT })}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PROFILE })}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.FAQ })}
/>
<DrawerItem
label='Atención al alumno'
onPress={() =>
props.navigation.navigate(focusedTab, { screen: Routes.student.STUDENT_SUPPORT })
}
/>
</DrawerContentScrollView>
);
}

Couldn't find a navigation object. Is your component inside NavigationContainer? error

I want to move on to the 'Detail' window when I touch the image of headerRight in the 'Main' window. But the "Couldn't find a navigation object. Is your component inside NavigationContainer?" error keeps popping up.
I think
<TouchableOpacity onPress={() => navigation.navigate('DETAIL')}>
<View>
<Image source={search} style={{height: 30, width: 30,marginRight:20}}/>
</View>
</TouchableOpacity>
this code is a problem, how should I fix it?
Also,
Can't find variable: navigation
error appears when I erase the const navigation = useNavigation(); code.
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { StyleSheet, Text, View,Image,ScrollView,TextInput, TouchableOpacity } from 'react-native';
import MainScreen from './MainScreen';
import DetailScreen from './DetailScreen';
import { useNavigation, StackActions } from '#react-navigation/native';
const Stack = createStackNavigator();
let search=require('./search.png')
function BackBtn() {
return (
<Image
source={require('./leftarrow.png')}
style={{marginLeft: 20, width: 15, height: 15}}
/>
);
}
export default function App() {
const navigation = useNavigation();
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='MAIN'>
<Stack.Screen name='MAIN' component={MainScreen}
options={{
title:'',
headerLeft:()=>
<View>
<Text style={{fontSize:25,marginLeft:30,marginTop:-5}}>성북구</Text>
</View>
,
headerRight:()=>
<TouchableOpacity onPress={() => navigation.navigate('DETAIL')}>
<View>
<Image source={search} style={{height: 30, width: 30,marginRight:20}}/>
</View>
</TouchableOpacity>
,
}}/>
<Stack.Screen name="DETAIL" component={DetailScreen}
options={{
title: '상세화면',
headerBackTitleVisible: false,
headerBackImage: BackBtn,
headerTitle:()=>(
<View>
<TextInput placeholder={'어떤 것을 찾고 계신가요?'} style={styles.input} autoFocus></TextInput>
</View>
)
}}/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
input:{
backgroundColor:'white',
marginTop:0,
marginLeft:0,
width:300,
fontSize:15,
paddingVertical:10,
paddingHorizontal:15
},
});
try this :
<Stack.Navigator
screenOptions={({ navigation }) => ({
headerRight: ()=>
<TouchableOpacity onPress={() => navigation.navigate('DETAIL')}>
<View>
<Image source={search} style={{height: 30, width: 30,marginRight:20}}/>
</View>
</TouchableOpacity>
})}
>
########### your routes here !
</Stack.Navigator>
i use react navigation V6.0.10
let me know if you need more informations or explication !

React Native - Show native header back icon

is there a way how to show native back icon (different for android nad iOS) in custom header? I have created custom header, but have no idea how to show them.
I'm using react-navigation version 6
My stack:
<Stack.Navigator screenOptions={
stackOptions({
header: (props: any) => <Header {...props}/>,
headerRight: () => HeaderActionIcon({
icon: <SvgSettings/>,
action: () => navigation.navigate('Settings')
})
})}>
My header component:
const Header = ({ ...props }: any) => {
const { options, navigation } = props
return (
<View style={styles.container}>
<Image
resizeMode='repeat'
source={require('../../assets/img/pattern.png')}
style={styles.image}
/>
<View style={styles.wrapper}>
{/* Back press icon */}
<View style={styles.leftItem}>
{/* Back icon should be here.. */}
</View>
{/* Stack title */}
<View style={styles.textWrapper}>
<Text style={[options.headerTitleStyle, styles.titleText]} numberOfLines={1}>
{ options.title }
</Text>
</View>
{/* Settings icon */}
<View style={styles.rightItem}>
{ options.headerRight() }
</View>
</View>
</View>
)}
Thanks for every answer
Here is a sample.
import * as React from 'react';
import { View, Text, Platform } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
React.useLayoutEffect(() => {
navigation.setOptions({
headerTitle: () =>
Platform.select({
android: <Text>{'Left android'}</Text>,
ios: <Text>{'Left ios'}</Text>,
}),
headerRight: () =>
Platform.select({
android: <Text>{'Right android'}</Text>,
ios: <Text>{'Right ios'}</Text>,
}),
});
}, []);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
import * as React from 'react';
import { View, Text, Platform } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
React.useLayoutEffect(() => {
navigation.setOptions({
headerTitle: () =>
Platform.select({
android: <Text>{'Left android'}</Text>,
ios: <Text>{'Left ios'}</Text>,
}),
headerRight: () =>
Platform.select({
android: <Text>{'Right android'}</Text>,
ios: <Text>{'Right ios'}</Text>,
}),
});
}, []);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

Navigation back click event in React Native

I am working on a React Native application. I am using navigation in my application. I want to do something when user presses back navigation i.e. moved to a back screen.
How can i get the click event of "blacked circle Frage" in the above image. I am working on IOS
Use a custom header with
import { Header } from "native-base";
And add below code in your route file to disable default header.
navigationOptions: {
header: null
}
my custome header code for your reference
<Header style={styles.header}>
<View style={{ flex: 2 }}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => { this.createNote(); this.props.navigation.navigate('Home') }}>
<Icon name="arrow-back" size={28} color="#606060" />
</TouchableOpacity>
</View>
<View style={{ flex: 8 }}></View>
<View style={{ flex: 2 }}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => { this.createNote(); this.props.navigation.navigate('Home') }}>
<Icon name="check" size={28} color="#606060" />
</TouchableOpacity>
</View>
</Header>
reference link:- https://www.npmjs.com/package/native-base
It probably varies depending on the libraries you are using. I am using react-native-paper in Expo, which uses the headerLeft option in the Stack.Screen component. Here's a complete example - save it and then 'expo start'
import { Provider as PaperProvider, Text } from 'react-native-paper'
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<PaperProvider>
<NavigationContainer >
<Stack.Navigator>
<Stack.Screen
name="Example"
options={{
title: 'Example',
headerLeft: () => <Text>Custom left button</Text>,
}}
component={() => <Text>Example body text</Text>}
/>
</Stack.Navigator>
</NavigationContainer>
</PaperProvider>
)
}
You can use onPress={() => this.props.navigation.goBack()} on TouchableOpacity if you are redirecting to the previous page
Also you can use this.props.navigation.navigate('Any_Screen') to move to other screens.
Also, I would like to suggest you to get familiar with BackHandler to move back to previous page when hardware back button is pressed.
add the code
onClick={this.props.navigation.goBack()}
or use specif navigation replace go back to
onClick={this.props.navigation.navigate('namepagespacific')}
check this screen there are mutiple example of handling click event
import React from 'react';
import { View, Text, StyleSheet, Button} from 'react-native';
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation, navigationOptions, screenProps }) => {
return {
title: navigation.getParam('title', 'A Nested Details Screen'),
};
};
render() {
const { navigation } = this.props;
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value');
return (
<View style={styles.detailsScreen}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details')}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.popToTop()}
/>
<Button
title="Update the title"
onPress={() => this.props.navigation.setParams({ title: 'Updated!' })}
/>
<Button
title="Modal"
onPress={() => this.props.navigation.navigate('MyModal')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
detailsScreen: {
flex: 1,
alignItems: "center",
justifyContent: "center"
}
})
export default DetailsScreen;
things you have asked in the comment section I could not find any exact answer for your question but you can take a look into this url how header buttons work
https://snack.expo.io/#react-navigation/simple-header-button-v3
hope this will work for you
header: ({ goBack }) => ({
left: ( <Icon name={'chevron-left'} onPress={ () => { goBack() } } /> ),
}),
you can also follow this page https://github.com/react-navigation/react-navigation/issues/779