ReactNative; How to call new component to open new screen? - react-native

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

Related

ReactNative Navigation to a screen in the same direcotry

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

cannot read property navigate of undefined

I am getting this error cannot read the property of navigate when try to navigate to the SignInScreen
this is the splash screen that have created
import React from 'react';
import {
View,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
StatusBar,
Image
} from 'react-native';
import * as Animatable from 'react-native-animatable';
import LinearGradient from 'react-native-linear-gradient';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { useTheme } from '#react-navigation/native';
const SplashScreen = ({navigation}) => {
const { colors } = useTheme();
return (
<View style={styles.container}>
<StatusBar backgroundColor='#009387' barStyle="light-content"/>
<View style={styles.header}>
<Animatable.Image
animation="bounceIn"
duraton="1500"
source={require('../assets/logo.png')}
style={styles.logo}
resizeMode="stretch"
/>
</View>
<Animatable.View
style={[styles.footer, {
backgroundColor: colors.background
}]}
animation="fadeInUpBig"
>
<Text style={[styles.title, {
color: colors.text
}]}>Stay connected with everyone!</Text>
<Text style={styles.text}>Sign in with account</Text>
<View style={styles.button}>
<TouchableOpacity onPress={()=>navigation.navigate('SignInScreen')}>
<LinearGradient
colors={['#08d4c4', '#01ab9d']}
style={styles.signIn}
>
<Text style={styles.textSign}>Get Started</Text>
<MaterialIcons
name="navigate-next"
color="#fff"
size={20}
/>
</LinearGradient>
</TouchableOpacity>
</View>
</Animatable.View>
</View>
);
};
export default SplashScreen;
this is the main App.js FILE WHICH IS THE ROOT FILE
const Drawer = createDrawerNavigator();
// const [isEnabled, setIsEnabled] = React.useState(false);
export default function App() {
return (
<PaperProvider theme={PaperDarkTheme}>
<SplashScreen />
</PaperProvider>
);
}
Looks like you missed to wrap main Navigation container and then drawer this can work :
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
const Drawer = createDrawerNavigator();
// const [isEnabled, setIsEnabled] = React.useState(false);
export default function App() {
return (
<PaperProvider theme={PaperDarkTheme}>
<NavigationContainer>
<Drawer.Navigator initialRouteName="splash">
<Drawer.Screen name="splash" component={SplashScreen } />
{// other Screens}
</Drawer.Navigator>
</NavigationContainer>
</PaperProvider>
);
}

screens are not navigating in react native

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.

How to pass data through stack navigation to a specific screen on react native tabs?

I'm creating a bottom tabs in react native, which will have two screens Home and News.
But first, user will need to Sign In and the users data will be passed from the login screen to Home screen. How do i pass those data. By using
navigation.navigate('Home', {Name: Name});
I can successfuly retrieve the data in Homescreen, if I just use two screen(Login and Home in a stack). However, when I change to navigate to the tabs(which includes Home and News), it doesnt work with error 'Undefined is not an object(evaluating 'route.params.Name'.
May you guys show me which part did I miss?
Here's the app.js code.
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import HomeScreen from './homescreen';
import NewsScreen from './newsscreen';
import LoginScreen from './loginscreen';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createStackNavigator } from '#react-navigation/stack';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
const LoginStack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<LoginStack.Navigator screenOptions={{headerShown: false}}
initialRouteName="Login">
<LoginStack.Screen name="Login"component={LoginScreen}/>
<LoginStack.Screen name="MyTabs" component={MyTabs} />
</LoginStack.Navigator>
</NavigationContainer>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Following is the homescreen code:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function HomeScreen({route, navigation}) {
var Name = route.params.Name;
return (
<View style={styles.container}>
<Text>{Name}</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
And finally here's the login code:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
export default function LoginScreen({navigation}) {
const Name = 'Boy';
const login = () => {
navigation.navigate('MyTabs', {Name: 'Boy'});}
return (
<View style={styles.container}>
<Text>LoginScreen</Text>
<TouchableOpacity
onPress={login}
><Text
>LOGIN</Text>
</TouchableOpacity>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
})
I'm trying to learn how to pass data from a screen to another screen, in which the screen is located inside a tab stack. I hope you guys can understand the question and provide me with your opinion and solution. Thanks.
Output:
It needed just this little modification in MyTabs component:
function MyTabs({ navigation, route }) {
const { name } = route.params;
console.log(name);
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={() => <HomeScreen name={route.params.name} />}
/>
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
Here is the working solution:
App.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 { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import HomeScreen from './home';
import NewsScreen from './newscreen';
import LoginScreen from './login';
// You can import from local files
const Tab = createBottomTabNavigator();
function MyTabs({ navigation, route }) {
const { name } = route.params;
console.log(name);
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={() => <HomeScreen name={route.params.name} />}
/>
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
const LoginStack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<LoginStack.Navigator
screenOptions={{ headerShown: true }}
initialRouteName="Login">
<LoginStack.Screen name="Login" component={LoginScreen} />
<LoginStack.Screen name="MyTabs" component={MyTabs} />
</LoginStack.Navigator>
</NavigationContainer>
);
}
export default App;
LoginScreen
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import React from "react";
export default function LoginScreen({ navigation }) {
const Name = 'Name From Login Screen';
const login = () => {
console.log("hi");
navigation.navigate('MyTabs', { name : Name });
}
return (
<View style={styles.container}>
<View style={styles.bottomView}>
<TouchableOpacity onPress={login} style={styles.button}>
<Text style={styles.textStyle}>LOGIN</Text>
</TouchableOpacity>
</View>
</View>
);
}
Home.js
import { Text, View, StyleSheet } from 'react-native';
import React from "react";
export default function HomeScreen({route, navigation, name}) {
console.log("***",name)
return (
<View style={styles.container}>
<Text style={styles.name}>{name}</Text>
</View>
);
}
Working Expo Snack example.
It's a little complicated to explain react native screens once you start combining bottomtabnavigator and stack navigator and even drawernavigation.
you may need to create stack navigation inside tab navigation like this.
//creating a separate stack within your tab
const HomeStack = createStackNavigator()
const HomeStackNavigator = () => {
return (
<HomeStack.Navigator screenOptions={{headerShown: false}}
initialRouteName="HomeScreen">
<HomeStack.Screen name="Home"component={HomeScreen}/>
</HomeStack.Navigator>
)
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator initialRouteName="HomeStackNavigator">
<Tab.Screen name="HomeStackNavigator" component={HomeStackNavigator} />
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
I believe, different navigators doesn't really talk to each other well. If you are using different navigator be prepare to nest stack navigators inside them.
The idea is, the parent of each display component should be a stack navigator. This will also allow you to better control your screenOptions.

TouchableRipple onPress is not working with react navigation

I am using stack navigator in my app to navigate through different components. but here I am facing 2 different issues. issue (1) I used a switch to toggle between dark and light theme, in the module, it works fine when using onPress but when called through stack screen it is not working. issue (2) I wanted to give some space between header text and the switch button but every time I add some padding to switch component, it is also applied to the header text. How can I solve these issues?
Here is App.js Component code:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React from 'react';
import {StatusBar, View} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import Home from './src/screens/Home';
import Details from './src/screens/Details';
import {createStackNavigator} from '#react-navigation/stack';
import {DarkTheme, Text, Title} from 'react-native-paper';
const Stack = createStackNavigator();
const App = () => {
const Darkthemebtntoggle = () => {
return (
<Details />
);
};
return (
<>
<NavigationContainer>
<StatusBar barStyle="dark-content" />
<Stack.Navigator screenOptions={{headerTitleAlign: ''}}>
<Stack.Screen
name="Home"
component={Home}
options={{
headerTitle: (props) => (
<Darkthemebtntoggle {...props} />
),
}}
/>
</Stack.Navigator>
</NavigationContainer>
</>
);
};
export default App;
Here is also Details.js component code:
import React, {useState} from 'react';
import {View, Text} from 'react-native';
import {TouchableRipple, Switch, Title} from 'react-native-paper';
function Details() {
const [isDartheme, setDarkTheme] = useState(false);
const togglemethod = () => {
setDarkTheme(!isDartheme);
};
return (
<View style={{flexDirection:"row"}}>
<View >
<Title>
<Text >Home</Text>
</Title>
</View>
<View style={{ paddingLeft:10, flexDirection:"row"}}>
<TouchableRipple
onPress={() => {
togglemethod();
}}>
<View pointerEvents="none">
<Switch value={isDartheme} />
</View>
</TouchableRipple>
</View>
</View>
);
}
export default Details;
Here is a screenshot of the behavior of the header: