I have a login screen then from there I navigate to home screen, and on home screen there are 4 buttons Alphabets, Ch-1,Ch-2 and Ch-3, by pressing each of those buttons, I can easily navigate to correct screens but Inside Alphabet screen, I have 2 more buttons Learn and Give test But when I press those, nothing happens , i can't navigate to the respective screens plus there are no errors. I guess its nested navigation.
I might sound stupid to an expert out there :) but I am new (from scratch) to react native and navigation stuff i really have no idea what to do! Will be really thankful if someone helps!
CODE IS GIVEN BELOW:
This is my home.js (its in folder screens):
import React from "react";
import {View, StyleSheet, Text} from 'react-native';
import { TouchableOpacity } from "react-native-gesture-handler";
import { Auth } from "../services";
export default home =({navigation}) => {
return (
<View style={styles.body}>
<Text style={styles.toptext}>
Merheba!
</Text>
<TouchableOpacity onPress={() => navigation.navigate('alphabets')}
style={styles.button}
>
<Text style={styles.buttontext}>Alphabets</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch1')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch2')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 2</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch3')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 3</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => Auth.signOut()}
style={styles.button}
>
<Text style={styles.buttontext}>Sign Out</Text>
</TouchableOpacity>
</View>
)
}
This is index.js from screens folder:
export {default as home} from './home';
export {default as login} from './login';
export {default as forgotp} from './login';
export {default as signup} from './signup';
export {default as alphabets} from './alphabets';
export {default as alphl} from './alphl';
export {default as alpht} from './alpht';
export {default as ch1} from './ch1';
export {default as ch2} from './ch2';
export {default as ch3} from './ch3';
This is alphabets.js from screens folder:
import { NavigationContainer } from "#react-navigation/native";
import React from "react";
import {View, StyleSheet, Text} from 'react-native';
import { TouchableOpacity } from "react-native-gesture-handler";
export default alphabets =({navigation}) => {
return (
<View style={styles.body}>
<Text style={styles.toptext}>
Merheba!
</Text>
<TouchableOpacity onPress={() => navigation.navigate('alphl')}
style={styles.button}
>
<Text style={styles.buttontext}>Learning Sheet</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('alpht')}
style={styles.button}
>
<Text style={styles.buttontext}>Give Test</Text>
</TouchableOpacity>
</View>
)
}
AppNavigation.js from navigation folder:
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import home from '../screens/home';
import alphabets from '../screens/alphabets';
import ch1 from '../screens/ch1';
import ch2 from '../screens/ch2';
import ch3 from '../screens/ch3';
const stack=createStackNavigator();
export default AppNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="home" component={home} />
<stack.Screen name="alphabets" component={alphabets} />
<stack.Screen name="ch1" component={ch1}/>
<stack.Screen name="ch2" component={ch2} />
<stack.Screen name="ch3" component={ch3} />
</stack.Navigator>
)
}
AlphNavigator.js from navigation folder:
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import alphl from '../screens/alphl';
import alpht from '../screens/alpht';
const stack=createStackNavigator();
export default AlphNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="alphl" component={alphl} />
<stack.Screen name="alpht" component={alpht} />
</stack.Navigator>
)
}
& lastly index.js from navigation folder:
import React, {useState, useEffect} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import AppNavigator from './AppNavigator';
import AuthNavigator from './AuthNavigator';
import auth from '#react-native-firebase/auth';
export default AppContainer = () => {
// Set an initializing state whilst Firebase connects
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState();
// Handle user state changes
function onAuthStateChanged(user) {
setUser(user);
if (initializing) setInitializing(false);
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
if (initializing) return null;
return(
<NavigationContainer>
{user ? <AppNavigator/> : <AuthNavigator/>}
</NavigationContainer>
)
}
You aren't defining your "AlphNavigator" in your "AppNavigator".
You should do this inside your AppNavigator:
export default AppNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="home" component={home} />
<stack.Screen name="alphabets" component={alphabets} />
<stack.Screen name="alph" component={ AlphNavigator } /> /*here add your AlpNavigator*/
<stack.Screen name="ch1" component={ch1}/>
<stack.Screen name="ch2" component={ch2} />
<stack.Screen name="ch3" component={ch3} />
</stack.Navigator>
)}
It's normal that you do not have any error in this case, because React Navigation does not mark you as an error if a screen does not exist.
The above could be solved if you were using TypeScript.
So now, in order to access to nested navigation screens you should use:
navigation.navigate('alph', { screen: 'alphl' })
The first parameter is the name of the stack navigation, and the second one is an object with the name of the screen inside to this nested navigation.
Related
I am very new to react native and I had one question to ask. I have two screens in the same directory
screens:
Pro.js
Register.js
in Pro.js , there is one button to navigate to Register.js
<Button
textStyle={{ fontFamily: 'montserrat-regular', fontSize: 12 }}
style={styles.button}
onPress={() => navigation.navigate("Register")}>
GET STARTED
</Button>
When I run above, I get below error:
The action 'NAVIGATE' with payload {"name":"Register"} was not handled by any navigator.
Do you have a screen named 'Register'?
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.
Can anyone help me to navigate to that page?
Check below code:
App.js
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import RegisterScreen from './RegisterScreen';
import HomeScreen from './HomeScreen';
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
HomeScreen.js
import React from 'react';
import { View, Text, Button } from 'react-native';
const HomeScreen = ({ navigation }) => {
return (
<View>
<Text>This is the Home screen</Text>
<Button
title="Go to Register"
onPress={() => navigation.navigate('Register')}
/>
</View>
);
};
export default HomeScreen
RegisterScreen.js
import React from 'react';
import { View, Text, Button } from 'react-native';
const RegisterScreen = () => {
return (
<View>
<Text>This is the Register screen</Text>
</View>
);
};
export default RegisterScreen
I want to open new screen from Nextpage.js ,after "onPress" worked, everything still same, NextPage not show on screen but not error. How should I do?
import NextPage from './NextPage';
function onClick() {
<NextPage/>
}
<TouchableHighlight onPress = {onClick}>
<View style={[styles.itemContainer, { backgroundColor: item.code }]}>
<Text style={styles.itemName}>{item.name}</Text>
<Text style={styles.itemCode}>{item.code}</Text>
</View>
</TouchableHighlight>
you can't call a screen like that. If you want to navigate to any other screen in your case NextPage, you should define it in your navigation stack first. After that, you can call function navigation.navigate("NextPage") to navigate to next page.
Navigator file:
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import * as React from 'react';
import Home from '../screens/Home';
import Next from '../screens/Next';
const Stack = createStackNavigator();
function App({initialRouteName = 'Home'}) {
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Home"
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Next" component={Next} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Suppose you are navigating from Home to NextPage
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
export default function Home(props) {
function onClick() {
props.navigation.navigate('NextPage');
}
return (
<TouchableHighlight onPress={onClick}>
<View style={[styles.itemContainer, {backgroundColor: item.code}]}>
<Text style={styles.itemName}>{item.name}</Text>
<Text style={styles.itemCode}>{item.code}</Text>
</View>
</TouchableHighlight>
);
}
const styles = StyleSheet.create({});
In this block of code, I want to use navigation.navigate to switch between the home screen and the profile screen. But when I run the app, I get the following error: can't find variable navigation.
I've been looking for a solution, but I can't seem to find it.
Here's the code:
import 'react-native-gesture-handler';
import * as React from 'react';
import {View, Text, Button} from 'react-native';
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
const HomeScreen = () => {
return(
<View>
<Text>Home Screen</Text>
<Button title="Go to Profile Screen" onPress={()=> navigation.navigate("Profile")}/>
</View>
);
}
const ProfileScreen = () => {
return(
<View>
<Text>Profile Screen</Text>
<Button title="Go to Home Screen" onPress={() => navigation.navigate("Home")}/>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={{ title: '' }}
/>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Thank you in advance.
You can get navigation object from props. Code example:
const HomeScreen = ({navigation}) => {
return(
<View>
<Text>Home Screen</Text>
<Button title="Go to Profile Screen" onPress={()=> navigation.navigate("Profile")}/>
</View>
);
}
I have a webview component in my project, where the flow being =>
The bottomTabBar opens the initial screen of the url that is given to Webview source prop, which should remain, when any link is clicked on the webview and it moves to another screen, the bottomtabbar should not come up.
Below is my WebviewScreen code :
import React, {Component} from 'react';
import {WebView} from 'react-native-webview';
import {View, SafeAreaView, ActivityIndicator} from 'react-native';
export default class ConsultationHomeScreen extends Component {
renderLoadingView = () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size="large" />
</View>
);
};
render() {
const {url} = this.props.route.params;
return (
<SafeAreaView style={{flex: 1}}>
<WebView
source={{uri: url}}
renderLoading={this.renderLoadingView}
startInLoadingState={true}
ref={(ref) => {
this.webview = ref;
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
this.webview.stopLoading();
}
}}
/>
</SafeAreaView>
);
}
}
And Appnavigation.js
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import LoginScreen from '../screens/authentication/LoginScreen';
import OtpScreen from '../screens/authentication/OtpScreen';
import AddChild from '../screens/Child/AddChild';
import AcceptInviteScreen from '../screens/AcceptInviteScreen';
import ConsultationHomeScreen from '../screens/ConsultationHomeScreen';
import HomeScreen from '../screens/HomeScreen/HomeScreen';
import PlansScreen from '../screens/PlansScreen';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function BottomTabBar() {
return (
<Tab.Navigator
lazy={false}
tabBarOptions={{
labelStyle: {
color: '#FF1493',
fontSize: 15,
},
}}>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: () => {
<MaterialIcon name="home" color="#FF1493" size={20} />;
},
}}
/>
<Tab.Screen
name="Consult"
component={ConsultationHomeScreen}
initialParams={{
url: 'some link',
}}
/>
<Tab.Screen name="Plans" component={PlansScreen} />
</Tab.Navigator>
);
}
export default function AppNavigation() {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none">
<Stack.Screen name="login" component={LoginScreen} />
<Stack.Screen name="otp" component={OtpScreen} />
<Stack.Screen name="addchild" component={AddChild} />
<Stack.Screen
name="acceptinvitescreen"
component={AcceptInviteScreen}
/>
<Stack.Screen name="home" component={BottomTabBar} />
</Stack.Navigator>
</NavigationContainer>
);
}
However, am unable to remove the bottomtabbar,could anyone please suggest how should I implement this behaviour?
Step1-> Webview initial screen renders and has bottomtabtabr
Step2-> Link clicked on the initial screen and navigates to next screen handled by web source
Step3->Bottom tab bar should not occur anywhere but only on the first initial screen
Please,any suggestion would be appreciated and let me know if anything else is required for better understanding.
I tested this modification in your source code and it works like a charm.
GIT difference in WebviewScreen.js :
## -23,6 +23,7 ## export default class ConsultationHomeScreen extends Component {
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
+ this.props.navigation.setOptions({ tabBarVisible: false });
this.webview.stopLoading();
}
}}
Let me know if you have any issue.
This is my App.js
import React from "react";
import Menu from "./components/Menu";
import HomeScreen from "./views/HomeScreen";
import SecondScreen from "./views/SecondScreen";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
const Stack = createStackNavigator();
export default function App() {
return (
<Container>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen name="Second" component={SecondSCreen} />
</Stack.Navigator>
</NavigationContainer>
<Menu></Menu>
</Container>
);
}
It works, because it shows the HomeScreen on default, but I want to navigate to the second screen via the Menu-component:
import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
class Menu extends React.Component {
render() {
return (
<View>
<TouchableOpacity
onPress={() => {
alert("Hi");
}}
>
<Text>HomeScreen</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
navigation.navigate("Second");
}}
>
<Text>Screen 2</Text>
</TouchableOpacity>
</View>
);
}
}
export default Menu;
The component is visible, but when I click on the second button I expect the SecondScreen to be openend.
But I get this error:
Can't find variable: navigation
What am I missing?
You should use the navigationRef for this scenario, as your menu is outside the navigation container
import { NavigationContainer } from '#react-navigation/native';
import { navigationRef } from './RootNavigation';
export default function App() {
return (
<Container>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen name="Second" component={SecondSCreen} />
</Stack.Navigator>
</NavigationContainer>
<Menu></Menu>
</Container>
);
}
// RootNavigation.js
import * as React from 'react';
export const navigationRef = React.createRef();
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
In menu js,
import {navigate} from 'RootNavigation';
class Menu extends React.Component {
render() {
return (
<View>
<TouchableOpacity
onPress={() => {
alert("Hi");
}}
>
<Text>HomeScreen</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
navigate("Second");
}}
>
<Text>Screen 2</Text>
</TouchableOpacity>
</View>
);
}
}