React Navigation: TypeError: undefined is not an object (evaluating 'navigation.navigate') Issue - reactjs

Facing issues while using react-navigation navigation.navigate functions.
TypeError: undefined is not an object (evaluating
'navigation.navigate')
import React from "react";
import { AccountBackground, AccountCover, Title} from "../components/account.styles";
import { MaterialIcons } from "#expo/vector-icons";
export const AccountScreen = ({ navigation }) => {
setTimeout(() => { navigation.navigate("Login");}, 3000);
return (
<AccountBackground>
<AccountCover />
<Title>Meals To Go</Title>
<MaterialIcons name="navigate-next" size={48} color="black" />
</AccountBackground>
);
};
import React, { useState, useEffect } from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import { AccountScreen } from "../../features/account/screens/account.screen";
import { LoginScreen } from "../../features/account/screens/login.screen";
import { RegisterScreen } from "../../features/account/screens/register.screen";
const Stack = createStackNavigator();
const createScreenOptions = { headerShown: false };
export const AccountNavigator = () => {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={createScreenOptions}>
<Stack.Screen name="Main" component={AccountScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Navigator>
</NavigationContainer>
);};

Related

React Native Custom Navbar issue

Hey so I am having a little brain meltdown,
I cannot for the life of me figure out how I should do this.
What I am trying to do is have my custom navbar not show on the login screen but show anywhere else.
I explained in this short video: https://cdn.discordapp.com/attachments/643261623519150090/904146526778056805/Desktop_2021.10.30_-_16.10.14.04.mp4
This is my code:
[ root ./ ] App.js
import LoginScreen from './views/login'
import HomeScreen from './views/home'
import ProfileScreen from './views/profile'
import CustomNav from './views/nav/index'
const Stack = createStackNavigator();
export default function App() {
return (
<View style={styles.Test} >
<NavigationContainer theme={DarkTheme} linking={{
config: {
screens: {
Login: "/",
Home: "/home",
Profile: "/Profile/:Username"
}
},
}}>
<Stack.Navigator
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
<CustomNav Nav="Mobile" />
</NavigationContainer>
</View>
);
}
[ ./nav/index] index.js
import React, {useEffect, useState} from 'react';
import {} from 'react-native';
import MobileNav from './mobile'
import WebsiteNav from './website'
const CustomNav = () => {
const [viewing, setViewing] = useState('login');
useEffect(() => {
if(viewing === 'login'){
console.log("Viewing Login")
}else{
console.log("Not Login")
}
}, []);
return(
null
);
}
export default CustomNav;

White screen after implement a custom router

First i will explain my problem, i created 3 screens.
Homepage, Login, Register
I try to implement firebase auth. If the user is connected -> Homepage, if not -> Welcome (welcome have 2 buttons, Login & Register)
I don't have any error and the is blank now with the Routes.js
Here is the code :
import { useEffect } from "react";
import { useContext, useState } from "react"
import { AuthContext } from "./providers/AuthProvider"
const Routes = () => {
const [user, setUser] = useContext(AuthContext);
const [initializing, setInitializing] = useState(true);
const onAuthstateChanged = (user) => {
setUser(user);
if(initilizing) setInitializing(false);
}
useEffect(() => {
const subscriber = auth().onAuthstateChanged(onAuthstateChanged);
return subscriber;
}, []);
if(initializing) return null
return (
user ? this.props.navigation.navigate('Home') : this.props.navigation.navigate('Intro')
)
}
export default Routes;
The code of my App.js
import React from 'react';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Welcome from './src/screens/account/Welcome';
import Intro from './src/screens/Intro';
import Home from './src/screens/Home';
import Login from './src/screens/account/Login';
import Register from './src/screens/account/Register';
import { Routes } from './src/Routes';
import { Dimensions, StatusBar, View } from 'react-native'
import { AuthProvider } from './src/providers/AuthProvider';
export default class App extends React.Component {
render() {
{
return (
<View style={{paddingTop: STATUSBAR_HEIGHT, flex: 1}}>
<AuthProvider>
<StatusBar translucent />
<NavigationContainer>
<Stack.Navigator initialRouteName="Routes">
<Stack.Screen name="Routes" component={Routes} options={{gestureEnabled: false}} />
<Stack.Screen name="Intro" component={Intro} options={{gestureEnabled: false}} />
<Stack.Screen name="Welcome" component={Welcome} options={{gestureEnabled: false}} />
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Register" component={Register} />
</Stack.Navigator>
</NavigationContainer>
</AuthProvider>
</View>
)
}
}
}
const STATUSBAR_HEIGHT = StatusBar.currentHeight;
const Stack = createStackNavigator();
Go this error now: Invalid attempt to destructure non-iterable instance. In order to be iterable, non(array objects must have a Symbol.iterator method.
Here is the code :
import React, { createContext, useState } from 'react';
import auth from '#react-native-firebase/auth';
export const AuthContext = createContext();
export const AuthProvider = ({children}) => {
const [user, setUser] = useState(null);
return (
<AuthContext.Provider
value={{
user,
setUser,
login: async (email, password) => {
try {
await auth().signInWithEmailAndPassword(email, password)
} catch(error) {
console.log(error)
}
},
register: async (email, password) => {
try {
await auth().createUserWithEmailAndPassword(email, password);
} catch (error) {
console.log(error)
}
},
logout: async () => {
try {
await auth().signOut();
} catch (error) {
this.setState({
errorMsg: translation(error.code)
})
}
}
}}
>
{children}
</AuthContext.Provider>
)
}

Testing: react-native (expo) take snapshot of a Screen component inside of react-navigation

My test attempt currently looks like this:
import React from "react"
import { NavigationContainer } from "#react-navigation/native"
import { createStackNavigator } from "#react-navigation/stack"
import { render, waitFor } from "#testing-library/react-native"
import { Provider } from "react-redux"
import { createStore } from "redux"
import rootReducer from "src/store/reducers/root-reducer"
import ProfileScreen from "src/screens/profile"
const store = createStore(rootReducer)
test("renders correctly", async () => {
const Screen = () => {
// const navigationRef = React.useRef(null) // cause "Invalid hook call. Hooks can only be called inside .."
const Stack = createStackNavigator()
return (
<Provider store={store}>
<NavigationContainer
// ref={navigationRef} // cause "Invalid hook call. Hooks can only be called inside .."
>
<Stack.Navigator>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
)
}
const tree = render(<Screen />)
await waitFor(async () => expect(tree.toJSON()).toMatchSnapshot())
})
But it keeps throwing this:
...
console.error
The above error occurred in the <ForwardRef(NavigationContainer)> component:
in Provider (created by Screen)
in Screen
Consider adding an error boundary to your tree to customize error handling behavior.
Visit <fb link> to learn more about error boundaries
...
I can't find any useful docs/examples on the react-navigation site regrading testing a screen. (I also googled a lot around)
I can try to boil down the code to something like this:
App.json
...
export default function App() {
...
return (
<Provider store={store}>
<Navigation />
</Provider>
)
}
Navigation.js
import React from "react"
import { NavigationContainer, DarkTheme } from "#react-navigation/native"
import { createStackNavigator } from "#react-navigation/stack"
import BottomTabNavigator from "./BottomTabNavigator"
export default function Navigation() {
const navigationRef = React.useRef(null)
return (
<NavigationContainer
theme={DarkTheme}
ref={navigationRef} // https://reactnavigation.org/docs/navigation-container/#ref
>
<RootNavigator />
</NavigationContainer>
)
}
const Stack = createStackNavigator()
function RootNavigator() {
return (
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Root" component={BottomTabNavigator} />
...
</Stack.Navigator>
)
}
BottomTabNavigator
import React from "react"
import { Linking, TouchableWithoutFeedback, View } from "react-native"
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs"
import { createStackNavigator } from "#react-navigation/stack"
import { Feather } from "#expo/vector-icons"
import Profile from "src/screens/profile"
import SignIn from "src/screens/sign-in"
const BottomTab = createBottomTabNavigator()
export default function BottomTabNavigator() {
const TabIcon = ({ name, color }) => <Feather name={name} color={color} size={20} />
return (
<BottomTab.Navigator
tabBarOptions={{
activeTintColor: Colors.defaultWhite,
style,
}}
>
<BottomTab.Screen
name="Profile"
component={ProfileNavigator}
options={{
tabBarIcon: ({ color }) => <TabIcon name="user" color={color} />,
title: I18n.t("components.tab_navigator.profile"),
}}
/>
)
}
const ProfileStack = createStackNavigator()
function ProfileNavigator() {
return (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={Profile} options={{ headerShown: false }} />
<ProfileStack.Screen name="SignIn" component={SignIn} options={{ headerShown: false }} />
</ProfileStack.Navigator>
)
}

ReactNative ERROR ,The action 'NAVIGATE' with payload was not handled by any navigator

I am using ReactNative application,
route.ts
import React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import Login from './src/screens/Login';
import Dashboard from './src/screens/Dashboard';
import {navigationRef} from './src/RootNavigation';
export const RootStack = createStackNavigator();
const Home = () => {
return (
<NavigationContainer ref={navigationRef}>
<RootStack.Navigator initialRouteName={'Login'}>
<RootStack.Screen name="Login" component={Login} />
<RootStack.Screen name="Dashboard" component={Dashboard} />
</RootStack.Navigator>
</NavigationContainer>
);
}
export default Home;
RootNavigation.ts
import React from 'react';
export const navigationRef: any = React.createRef();
export function navigate(name: any, params: any) {
navigationRef.current.navigate(name, params);
}
Login.tsx
import * as Navigation from '../RootNavigation';
loginAttempt = () => {
if (
this.state.username === this.props.userData.username &&
this.state.password === this.props.userData.password
) {
Navigation.navigate('Dashboard ', {});
} else {
Alert.alert('Please try again with correct username and password');
}
};
Here I am facing issues error while navigating from one screen to another screen;
The action 'NAVIGATE' with payload {"name":"Dashboard ","params":{}} was not handled by any navigator.
Do you have a screen named 'Dashboard '?
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.
Navigation Container
let navigator;
<NavigationContainer
ref={(nav: any) => {
navigator = nav;
NavigationService.setNavigator(navigator);
}}>
<RootStack.Navigator initialRouteName={'Login'}>
<RootStack.Screen name="Login" component={Login} />
<RootStack.Screen name="Dashboard" component={Dashboard} />
</RootStack.Navigator>
</NavigationContainer>
Navigation Service
import { CommonActions, StackActions } from '#react-navigation/native';
const config: any = {};
export function setNavigator(nav: any) {
if (nav) {
config.navigator = nav;
}
}
export function navigate(name: any, params?: any) {
if (config.navigator && name) {
const action = CommonActions.navigate({ name, params });
config.navigator.dispatch(action);
}
}
export function goBack() {
if (config.navigator) {
const action = CommonActions.goBack();
config.navigator.dispatch(action);
}
}
export function popToTop() {
if (config.navigator) {
const action = StackActions.popToTop();
config.navigator.dispatch(action);
}
}
Usage
import * as NavigationService from 'path';
Navigation.navigate('Dashboard');
I think your way should works as well but you have a space here Navigation.navigate('Dashboard ', {}) instead of Navigation.navigate('Dashboard', {});

How do I pass a state object to a screen in React Native?

** i want to pass the setScreen object to Signup screen
please tell me how do i pass it so i could change the screen state from Signup screen**
import React, { useState } from 'react';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import AccountScreen from './src/screens/AccountScreen';
import SigninScreen from './src/screens/SigninScreen';
import SignupScreen from './src/screens/SignupScreen';
import TrackCreateScreen from './src/screens/TrackCreateScreen';
import TrackDetailScreen from './src/screens/TrackDetailScreen';
import TrackListScreen from './src/screens/TrackListScreen';
const Stack = createStackNavigator();
const TrackStack = createStackNavigator();
const Tab = createBottomTabNavigator();
const TrackScreenStack = () => {
return (
<TrackStack.Navigator initialRouteName="TrackList">
<TrackStack.Screen
name="TrackList"
component={TrackListScreen}
/>
<TrackStack.Screen
name="TrackDetail"
component={TrackDetailScreen}
/>
</TrackStack.Navigator>
)
}
** here i have declared the state object
and i wish to pass it in Signup screen
so that i could switch between screen stacks**
const App = () => {
const [screen, setScreen] = useState(true);
return (
<NavigationContainer>
{screen ? (
<Stack.Navigator initialRouteName="Signup">
<Stack.Screen
name="Signup"
component={SignupScreen}
/>
<Stack.Screen
name="Signin"
component={SigninScreen}
/>
</Stack.Navigator>
) :
<Tab.Navigator>
<Tab.Screen
name="Track"
component={TrackScreenStack}
/>
<Tab.Screen
name="Account"
component={AccountScreen}
/>
<Tab.Screen
name="TrackCreate"
component={TrackCreateScreen}
/>
</Tab.Navigator>
}
</NavigationContainer>
)
}
export default App;

Resources