React native navigation between 2 screens - reactjs

I am new in react native and I don't understand why it is not working
In my main file App.js , I need to have a button to go to another screen( AddList.js)
So, In app.js , I have
function App (navigation) {
const onPressHandler = () => {
navigation.navigate('AddList')
}
return (
<Pressable onPress={onPressHandler}>}
function addList(navigation) {
const onPressHandler = () => {
navigation.goBack();
}
return(
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={App}
/>
<Stack.Screen
name="FavProducts"
component={FavProducts}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
There are in the same file App.js
Sorry for the question and thanks to your help
I have try with reactnative doc , but not working

If you are using #react-navigation/native then first you need to create container to handle the component state and then you have to create stack
in side the stack you need to define your screens like this.
import React from 'react';
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import AddList from './components/screens/AddList';
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
component={AddList}
name="AddList"
options={{ headerShown: false }}
/>
// define your screens as well
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
and if you have to move from one screen to another then import in your js file where you have to create the click event
import { useNavigation } from '#react-navigation/native';
const navigation = useNavigation();
and on button press
navigation.navigate('AddList')

Related

How to add and remove screens to RAM manually through code in React Native

Problem
I am new to React Native. Recently I faced with such a problem: when I move from the login screen to the signup screen, the signup screen is loaded again each time. How I can load the screen only once and store it in RAM or do something like that, to avoid rerendering? How to add and remove screens to RAM manually through code.
Environment
MacOS 13.0.1 (M1)
React Native CLI
dependencies:
#react-navigation/native: ^6.1.2,
#react-navigation/stack: ^6.3.11,
expo-linear-gradient: ^12.0.1,
react: 18.1.0,
react-native: ^0.70.6,
react-native-color-picker: ^0.6.0,
react-native-event-listeners: ^1.0.7,
react-native-gesture-handler: ^2.9.0,
react-native-localization: ^2.3.1,
react-native-paper: ^5.1.3,
react-native-paper-dropdown: ^1.0.7,
react-native-safe-area-context: ^4.4.1,
react-native-screens: ^3.19.0,
react-native-vector-icons: ^9.2.0,
Code
App.navigator.tsx
import React from "react"
import { createStackNavigator, StackView } from "#react-navigation/stack"
import { NavigationContainer } from "#react-navigation/native"
import { SignupScreen } from "./screens/signup/signup.screen"
import { LoginScreen } from "./screens/login/login.screen"
import { HomeScreen } from "./screens/home/home.screen"
import { SettingsScreen } from "./screens/settings/settings.screen"
const Stack = createStackNavigator()
// App navigation. Used to relocate between the app's screens
const AppNavigator = () => (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false,
headerMode: "screen",
cardStyle: {backgroundColor: "white"}}}
initialRouteName="Login">
<Stack.Screen name="Login"
component={LoginScreen} />
<Stack.Screen name="SignUp"
component={SignupScreen} />
<Stack.Screen name="Home"
component={HomeScreen} />
<Stack.Screen name="Settings"
component={SettingsScreen} />
</Stack.Navigator>
</NavigationContainer>
)
export default AppNavigator
App.tsx
import React, {useState, useEffect} from 'react';
import {Provider as PaperProvider} from 'react-native-paper';
import { EventRegister } from 'react-native-event-listeners';
import AppNavigator from './app.navigator';
import mainAppTheme, {fontTheme} from './config/theme';
import themeContext from './config/themeContext';
import { CHANGE_THEME_LITERAL } from './config/theme';
const App = () => {
// Theme update
const [theme, setTheme] = useState(mainAppTheme)
useEffect(() => {
let eventListener = EventRegister.addEventListener(CHANGE_THEME_LITERAL, (theme) => {
setTheme(theme)
})
return () => {
EventRegister.removeEventListener(eventListener.toString())
}
})
return (
<themeContext.Provider value={theme}>
<PaperProvider theme={fontTheme}>
<AppNavigator />
</PaperProvider>
</themeContext.Provider>
);
};
export default App;
Login.screen.tsx
import React, { useContext, useState } from "react";
import { SafeAreaView, View } from "react-native";
import { Button, Card, TextInput } from "react-native-paper";
import { PasswordComponent } from "../../components/password.component";
import mainAppTheme, {appTheme} from "../../config/theme";
import themeContext from "../../config/themeContext";
import { loginScreenTrans } from "../../translations/login.screen.trans"
import { loginStyle } from "./login.style";
interface LoignScreenProps{
navigation: any
}
// Login app screen. Meets new users
export const LoginScreen = (props:LoignScreenProps) => {
// Theme update
const theme: appTheme = useContext(themeContext)
loginScreenTrans.setLanguage(theme.lang)
return(
<SafeAreaView style={loginStyle().content}>
<View style={loginStyle().view}>
<Card>
<Card.Title title="BuildIn" titleStyle={loginStyle().cardTitle}></Card.Title>
<Card.Content>
<TextInput selectionColor={theme.colors.mainAppColor}
activeUnderlineColor={theme.colors.mainAppColor}
label={loginScreenTrans.email}
keyboardType="email-address"
style={loginStyle().email} />
<PasswordComponent label={loginScreenTrans.password}
color={theme.colors.mainAppColor.toString()}
style={loginStyle().password}/>
<Button uppercase={false}
textColor={theme.colors.mainAppTextColor}>
{loginScreenTrans.forgot}
</Button>
<Button buttonColor={theme.colors.mainAppColor}
textColor={"#ffffff"}
uppercase={true}
mode="contained"
onPress={() => {props.navigation.navigate("Home");
props.navigation.reset({
index: 0,
routes: [{ name: 'Home' }]})
}}>
{loginScreenTrans.login}
</Button>
<Button uppercase={true}
textColor={mainAppTheme.colors.mainAppTextColor}
onPress={() => props.navigation.navigate("SignUp")}>
{loginScreenTrans.signup}
</Button>
</Card.Content>
</Card>
</View>
</SafeAreaView>
);
}
What i tried
Next steps changed nothing in my case:
Use enableFreeze(true) and enableScreens(true) at the top of loaded screen file and top of navigation file.
Wrap my screen in React.memo()
Set freezeOnBlur: true prop into <Stack.Navigator>
navigation.dispatch(CommonActions.reset({ routes[...]
Maybe I used it incorrectly, I would be grateful if someone could explain to me why.
But it seems that the problem is specifically in the way react navigation works. And I don't know how to set it up the way I want.

Error in React Native Bottom Tab Navigation

I'm trying to use BottomTabNavigator in a new project but I am getting an error i had never seen.
This is the error
Error: A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. path: ''.
I use bottom Tab Navigation in few projects and I had never got this strange error, it seems a ReactJS error more than react native
This is my TabNavigator
import React from 'react';
import { View } from 'react-native';
import { NavigatorKeys } from '../screens';
const test = () => <View />;
function TabNavigator() {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator>
<Tab.Screen name={NavigatorKeys.tab} component={test} />
</Tab.Navigator>
);
}
export default TabNavigator;
and this is the usage:
<Stack.Navigator screenOptions={headerWithAnimationOptions} initialRouteName={NavigatorKeys.tab}>
<Stack.Screen name={NavigatorKeys.tab} component={TabNavigator} />
<Stack.Screen name={ScreenKeys.dashboard} component={Dashboard} options={dashboardOptions} />
<Stack.Screen name={ScreenKeys.noticeBoard} component={NoticeBoard} options={noticeBoardOptions} />
</Stack.Navigator>
do you have any idea what the problem might be? Thanks

React Native Stack Navigator only working from home?

I have a scenario where I'm trying to use multiple stack navigators within my React Native application.
At the moment I have a StackNavigator set up within
navigation>Home.js
I want a second StackNavigator set up for my ProfileScreen so I have created a second file navigation>ProfileStack.js
Ideally I'd really not want to have the home containing the stack screen because a user can not go from Home > EditProfileScreen. This also causes a bit of a bug where when the app on launch it loads the profile first and if you select edit profile it says "The action 'NAVIGATE' with payload {"name":"EditProfileScreen"} was not handled by any navigator."
However if I open the drawer navigator, go to the home page, then back through the drawer navigator to the profile page, I can go into edit profile. Though the stack when you swipe back goes to home and not the profile page. I understand this is because currently the Home.js contains the Stack.Screens. (It doesn't work if I don't have them there)
Big explanation but thought a lot of detail was better than minimal. The app.js renders the which contains the drawer navigator which loads on launch.
**ProfileStack.js**
import React from 'react';
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import EditProfileScreen from '../screens/EditProfileScreen';
import { NavigationContainer } from '#react-navigation/native';
import ProfileScreen from '../screens/ProfileScreen';
import UserFavouritesScreen from '../screens/UserFavouritesScreen';
const Stack = createNativeStackNavigator();
function ProfileStack(props) {
return(
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="ProfileScreen" component={ProfileScreen}/>
<Stack.Screen name="EditProfileScreen" component={EditProfileScreen}/>
<Stack.Screen name="UserFavouritesScreen" component={UserFavouritesScreen}/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default ProfileStack;
**Home.js**
import React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer'
import HomeScreen from '../screens/HomeScreen';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { KeyboardAvoidingView, Platform } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import MapScreen from '../screens/MapScreen';
import WalkingScreen from '../screens/WalkingScreen';
import TourDetail from '../screens/TourDetail';
import { TouchableOpacity } from 'react-native';
import tw from 'twrnc';
import { Icon } from "react-native-elements";
import { useNavigation } from "#react-navigation/native";
import EditProfileScreen from '../screens/EditProfileScreen';
import ProfileScreen from '../screens/ProfileScreen';
import UserFavouritesScreen from '../screens/UserFavouritesScreen';
const HomeNavigator = (props) => {
const Stack = createNativeStackNavigator();
const navigation = useNavigation();
return (
<KeyboardAvoidingView //This ensures that the keyboard does not hide whats behind
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{flex: 1}}
keyboardVerticalOffset={Platform.OS === "ios" ? -64 : 0}
>
<TouchableOpacity
onPress={() => navigation.toggleDrawer()}
style={tw`bg-gray-100 absolute top-16 left-8 z-50 p-3 rounded-full shadow-lg`}>
<Icon name="menu" />
</TouchableOpacity>
{/* <AuthStack /> */}
<Stack.Navigator
screenOptions={{headerShown: false, }}
>
<Stack.Screen name='HomeScreen' component={HomeScreen} />
<Stack.Screen name='MapScreen' component={MapScreen} />
<Stack.Screen name='WalkingScreen' component={WalkingScreen} />
<Stack.Screen name='TourDetail' component={TourDetail} />
*<Stack.Screen name="ProfileScreen" component={ProfileScreen}/>
<Stack.Screen name="EditProfileScreen" component={EditProfileScreen}/>
<Stack.Screen name="UserFavouritesScreen" component={UserFavouritesScreen}/>*
</Stack.Navigator>
</KeyboardAvoidingView>
);
};
export default HomeNavigator;
```

can't find variable: user. I am using firebase auth and the latest SDK, expo SDK 42, react navigation 6.x.x

import { StyleSheet, Text, View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import LoginScreen from "./screens/LoginScreen";
import SignUpScreen from "./screens/SignUpScreen";
import WelcomeScreen from "./screens/WelcomeScreen";
import OnBoard from "./screens/Onboard";
import GetStarted from "./screens/GetStarted";
import { auth } from "./firebase";
const Stack = createNativeStackNavigator();
export default function App() {
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
console.log(user);
return user;
});
return unsubscribe;
}, []);
return (
<NavigationContainer>
<Stack.Navigator>
{user ? (
<>
<Stack.Screen
options={{ headerShown: false }}
name="OnBoard"
component={OnBoard}
/>
<Stack.Screen
options={{ headerShown: false }}
name="SignUp"
component={SignUpScreen}
/>
<Stack.Screen
options={{ headerShown: false }}
name="Login"
component={LoginScreen}
/>
</>
) : (
<Stack.Screen
options={{ headerShown: false }}
name="Welcome"
component={WelcomeScreen}
/>
)}
</Stack.Navigator>
</NavigationContainer>
);
}
can't find variable :user, I can't understand also I am new to react-native and react-navigation. I tried returning user but unlined or something.
tried
const isLoggedIn = user;
console.log(isLoggedIn)
It just logs undefined. Anyone can help me with it?
I am using firebase auth and the latest SDK, expo SDK 42, react navigation 6.x.x Using condition rendering for the to hide the onBoarding, logIn and signUp screen when the app loads and the user is authenticated so he directly does to welcomeScreen
Link to the expo snack. Run it in your device not on the web. https://snack.expo.dev/#bishalsaha/a638cf
It seems that you are trying to use the 'firebase' package for web and node instead the RN one. (even you also have the RN ones in your package.json)
Try to follow these instructions:
https://rnfirebase.io/auth/usage#listening-to-authentication-state

Updating syntax for AppNavigator in react-native app using react-navigation v5

In my react-native app I am in the process of upgrading to react-navigation v5. For AppNavigator, which is passed into my main App.js file, the old code looks like this:
import { createAppContainer, createSwitchNavigator, createStackNavigator } from 'react-navigation';
import LoginScreen from '../screens/LoginScreen';
import LoadingScreen from '../screens/LoadingScreen';
const AuthStack = createStackNavigator({
Login: LoginScreen,
Loading: LoadingScreen
});
import MainDrawerNavigator from './DrawerNavigator';
export default createAppContainer(createSwitchNavigator({
Main: MainDrawerNavigator,
Auth: AuthStack
},
{
initialRouteName: 'Auth',
}));
The code gets used in App.js like so:
<Provider store={store}>
<NavigationContainer ref={navigationRef}>
<View style={styles.container}>
{Platform.OS === 'ios' && <StatusBar barStyle="light-content" />}
<AppNavigator ref={nav => { navigatorRef = nav }} /> // AppNavigator used here
</View>
</NavigationContainer>
</Provider>
From what I can tell, createAppContainer is no longer the way to handle this in react-navigation v5. I'm getting an error on this import specifically:
import { createAppContainer, createSwitchNavigator, createStackNavigator } from 'react-navigation';
... partly because the directory structure for the location of these kinds of imports has changed. But from what I can tell, createAppContainer is not existent now? In other words, it's not just an issue of it being located somewhere else now. Correct me if I'm wrong.
So my question is, what should this code look like in v5? Any insight would be appreciated. I'm referring to this AppNavigator code:
import { createAppContainer, createSwitchNavigator, createStackNavigator } from 'react-navigation';
import LoginScreen from '../screens/LoginScreen';
import LoadingScreen from '../screens/LoadingScreen';
const AuthStack = createStackNavigator({
Login: LoginScreen,
Loading: LoadingScreen
});
import MainDrawerNavigator from './DrawerNavigator';
export default createAppContainer(createSwitchNavigator({
Main: MainDrawerNavigator,
Auth: AuthStack
},
{
initialRouteName: 'Auth',
}));
Firstly first you need import NavigationContainer to contain all of your navigations
import { NavigationContainer } from '#react-navigation/native'
then after that create your StackNavigator like this
import { createStackNavigator } from '#react-navigation/stack'
const Stack = createStackNavigator()
import LoginScreen from '../screens/LoginScreen'
import LoadingScreen from '../screens/LoadingScreen'
function AuthStack() {
return (
<Stack.Navigator>
<Stack.Screen
name = "LoginScreen"
component = {LoginScreen}
/>
<Stack.Screen
name = "LoadingScreen"
component = {LoadingScreen}
/>
</Stack.Navigator>
)
}
next, create the drawer navigator
import { createDrawerNavigator } from '#react-navigation/drawer'
const MainDrawer = createDrawerNavigator()
finally the App function will looks like this
import { NavigationContainer } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
import { createDrawerNavigator } from '#react-navigation/drawer'
const Stack = createStackNavigator()
import LoginScreen from '../screens/LoginScreen'
import LoadingScreen from '../screens/LoadingScreen'
function AuthStack() {
return (
<Stack.Navigator>
<Stack.Screen
name = "LoginScreen"
component = {LoginScreen}
/>
<Stack.Screen
name = "LoadingScreen"
component = {LoadingScreen}
/>
</Stack.Navigator>
)
}
const MainDrawer = createDrawerNavigator()
export default function App() {
return (
<NavigationContainer>
<MainDrawer.Navigator
initialRouteName = "Auth"
>
<MainDrawer.Screen
name = 'Auth'
component = {AuthStack}
/>
<MainDrawer.Screen
name = 'YourDrawerScreen'
component = {YourDrawerScreen}
/>
</MainDrawer.Navigator>
</NavigationContainer>
)
}
I don't think there is Switch Navigator in React-Navigation v5

Resources