Open a new screen through a tab screen - react-native

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

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

How to keep track of screen title when bottom navigation is used in react native?

I am making use of bottom navigation in React Native and I have a header which is supposed to show on which screen I am at the moment. I am not sure how to change that text on Tab Bar press. I tried making use of onPress event but seems like it does not work.
Here is my code:
<View style={styles.container}>
<StatusBar barStyle="light-content" />
<View style={styles.header}>
<Text style={styles.headerText}>{headerText}</Text>
<SettingsIcon />
</View>
<View style={styles.main}>
<NavigationContainer >
<Tab.Navigator initialRouteName="Home" tabBarOptions={{
activeTintColor: '#FF9F0A',
inactiveTintColor:'white',
style: {
backgroundColor: '#000000',//color you want to change
}
}}>
<Tab.Screen name="Home" component={Home} options={{
tabBarLabel: 'HOME',
tabBarIcon: ({ color, size }) => (
<HomeTabIcon name="home" color={color} size={size} />
),
}}/>
<Tab.Screen name="Controls" component={Controls} options={{
tabBarLabel: 'CONTROLS',
tabBarIcon: ({ color, size }) => (
<ControlsTabIcon name="controls" color={color} size={size} />
),
}}/>
<Tab.Screen name="Charging" component={Charging} options={{
tabBarLabel: 'CHARGING',
tabBarIcon: ({ color, size }) => (
<ChargingTabIcon name="charging" color={color} size={size} />
),
}}/>
</Tab.Navigator>
</NavigationContainer>
</View>
</View>
you can nest your tab navigator in a screen navigator.
You can change the title of your screen navigator header in function of the name of your active screen.
for more information read this.
import React from 'react';
import { NavigationContainer, getFocusedRouteNameFromRoute } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const RootStack = createStackNavigator();
const Tab = createBottomTabNavigator();
function getHeaderTitle(route : any) {
// If the focused route is not found, we need to assume it's the initial screen
// This can happen during if there hasn't been any navigation inside the screen
// In our case, it's "Feed" as that's the first screen inside the navigator
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
console.log("name route = ", routeName);
switch (routeName) {
case 'Home':
return 'name header tab1';
case 'tab1':
return 'name header tab1';
case 'tab2':
return 'name header tab2';
}
}
const HomeTabs = () => {
return (
<Tab.Navigator>
<Tab.Screen name="tab1" component={Component1} />
<Tab.Screen name="tab2" component={Component2} />
</Tab.Navigator>
);
};
function Root() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="Home"
component={HomeTabs}
options={({ route }) => ({
headerTitle: getHeaderTitle(route),
})}
/>
</RootStack.Navigator>
</NavigationContainer>
);
};

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.

React Native: where to place Navigators for other screens?

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>