this.props.navigation.navigate() not working - javascript

I want the app to check if there's a user logged in (firebase authentication). If there is, navigate to one page (react navigation v5), if there isn't, to another.
I have the following code:
In App.js
//import navigation + screens
const Stack = createStackNavigator();
const MaterialBottomTabs = createMaterialBottomTabNavigator();
class App extends React.Component {
AuthStack = () => {
<Stack.Navigator>
<Stack.Screen name="login" component={LoginScreen} />
<Stack.Screen name="register" component={RegisterScreen} />
</Stack.Navigator>
}
createBottomTabs = () => {
return <MaterialBottomTabs.Navigator>
<MaterialBottomTabs.Screen name="first" component={firstScreen} />
<MaterialBottomTabs.Screen name="second" component={secondScreen} />
</MaterialBottomTabs.Navigator>
}
render(){
return(
<LoadingScreen />
)
}
}
export default App;
In Loading.js
import React from "react";
import { Text, SafeAreaView } from "react-native";
import * as firebase from "firebase";
import {AuthStack, createBottomTabs} from "./App.js";
class LoadingScreen extends React.Component {
componentDidMount() {
firebase.auth().onAuthStateChanged((user) => {
this.props.navigation.navigate(user ? createBottomTabs : AuthStack);
});
}
render() {
return (
<SafeAreaView>
<Text>
Waiting...
</Text>
</SafeAreaView>
);
}
}
export default LoadingScreen;
I get an error which says:
TypeError: undefined is not an object (evaluating '_this.props.navigation.navigate')

The navigation prop is not passed into all components, only screen components receive this prop automatically! If, however, you wish to access the navigation prop in any of your components, you may use the useNavigation hook.
Here is an example from the docs
import * as React from 'react';
import { Button } from 'react-native';
import { useNavigation } from '#react-navigation/native';
function MyBackButton() {
const navigation = useNavigation();
return (
<Button
title="Back"
onPress={() => {
navigation.goBack();
}}
/>
);
}

Related

React navigator not moving between screens

My app closes when I press the switch screen button. I don't see any error output.
I did a version check and there was no problem.
The function I wrote for the button works
Router.js
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import First from "./First";
import Second from "./Second";
const Stack = createNativeStackNavigator();
const Router = () =>{
return(
<NavigationContainer>
<Stack.Navigator initialRouteName="First">
<Stack.Screen name="First" component={ First }/>
<Stack.Screen name="Second" component={ Second }/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default Router;
First.js
import React from 'react';
import {View,Text,Button} from 'react-native';
const First = ( props ) =>{
const gotoSecond = () => {
console.log("First");
props.navigation.navigate("Second");
console.log("second")
}
return (
<View>
<Text>Hello First Page!</Text>
<Button title="Go SecondPage!" onPress={gotoSecond}/>
</View>
);
};
export default First;
Second.js
import React from 'react';
import {View,Text} from 'react-native';
const Second = () =>{
return (
<View>
<Text>Hello Second Page!</Text>
</View>
);
};
export default Second;
OS:Android,
Emulator:Genymotion.
Now I'm using ADV instead of Genymotion, problem solved.

Undefined is not an object (evaluating 'navigation.navigate') when trying to navigate between two sites React Native

I try to navigate between two pages in a React Native app. I keep getting errors for my implementations but I don't know why.
I have the following setup for a "Home" and "Settings" site in the React Native app with Navigator adjusted from the documentation:
App.js
import Home from "./Home";
import { NavigationContainer } from '#react-navigation/native';
export default function App() {
return <NavigationContainer><Home/></NavigationContainer>
}
Home.jsx
const Home = ({ navigation }) => {
return (
<View style={["some style...", {}]}>
<View style={["some style..."]}>
<TouchableOpacity onPress={() =>
navigation.navigate('Settings')}>
<Image "some image..."/>
</TouchableOpacity>
</View>
</View>
Settings.jsx
A component which should be rendered.
MyStack.jsx
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Home from './Home';
import Settings from './Settings';
const Stack = createNativeStackNavigator();
const MyStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
/>
<Stack.Screen name="Settings" component={Settings} />
</Stack.Navigator>
</NavigationContainer>
);
};
I get undefined is not an object (evaluating 'navigation.navigate'). Also adding this.props to navigation.navigate('Settings') throws and error. I am just not able to access my Navigator.
You seem to be setting up a navigator but never using it, since in App.js you are just calling <Home/>.
Change App.js to this:
import MyStack from "./MyStack"; // Use the correct path for the import
export default function App() {
return <MyStack/>
}
Add at the end of MyStack.jsx:
export default MyStack;

TypeError: _this.props.loginState is not a function

When the user presses the login button the Drawer.Navigation needs to change (I try to learn the basics so no form for the login needed). When I try to pass this action to App.js I get this Error:"TypeError: _this.props.loginState is not a function"
According to the errormessage the problem should be in this pice of code:
changeLoginState = () => {
this.props.loginState(true)
}
This is the code of App.js
import * as React from 'react';
import { getFocusedRouteNameFromRoute, NavigationContainer } from '#react-navigation/native';
import { createAppContainer } from "react-navigation";
import { RootNavigator } from './src/navigation/AppNavigator';
import { PropTypes } from 'react'
//navigation
import { createDrawerNavigator } from '#react-navigation/drawer'
import Account from './src/screens/account';
import Login from './src/screens/Login'
export default function App(){
let isLoggedIn = false
function changeLoginState(newState){
isLoggedIn = newState
}
const Drawer = createDrawerNavigator();
let d
let p
let l
if(isLoggedIn){
d = <Drawer.Screen name="Account" component={Account}/>
}else{
d = <Drawer.Screen name="Inloggen" component={Login} loginState={changeLoginState}/>
}
return(
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
{d}
</Drawer.Navigator>
</NavigationContainer>
)
}
And this is the code of Login comoponent: Login.js
import * as React from 'react';
import { Component } from 'react';
import { View, Button, StyleSheet, TouchableOpacity} from 'react-native';
class Login extends Component {
constructor(props){
super(props)
}
changeLoginState = () => {
this.props.loginState(true)
}
render(){
return (
<View style={{display: 'flex', justifyContent:'center', alignItems:'center', height: '100vh'}}>
<TouchableOpacity style={{backgroundColor: 'red'}} onPress={ () => this.changeLoginState() }>Login</TouchableOpacity>
</View>
);
}
}
export default Login
I have seen a lot of similar questions but nothing worked.
If you have other remarks on my code, feel free to comment.
I thank you.
Use options to pass props to screen:
options={{ loginState: changeLoginState }}

React Native: Passing navigation route as props into dynamically rendered component

I am building an app in which several of the screens have dynamically rendered cards that are mapped to an array of objects called ENTRIES. Each one of these cards can be pressed to navigate to a corresponding screen, however, I cannot seem to get the navigation to work.
I am passing is the screen value from ENTRIES as props from the Settings.js screen into the ClickableCard component, which then gets passed into the TouchableOpacity onClick as this.props.navigation.navigate(screen).
However I keep getting the following error TypeError: undefined is not an object (evaluating '_this3.props.navigation.navigate')
Here is an example of the code below:
App.js File
import React from 'react;
import {createMaterialBottomTabNavigator} from '#react-navigation/material-bottom-tabs';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import Home from './src/screens/Home';
import SettingsScreen from './src/screens/SettingsScreen';
import PrivacyScreen from './src/screens/PrivacyScreen';
import NotificationsScreen from './src/screens/NotificationsScreen';
import SoundsScreen from './src/screens/SoundsScreen';
import ThemeScreen from './src/screens/ThemeScreen';
const PrivacyStack = createStackNavigator();
const SettingsStack = createStackNavigator();
const AuthStack = createStackNavigator();
const MainStack = createStackNavigator();
const Tabs = createMaterialBottomTabNavigator();
const TabNavigator = () => {
return (
<Tabs.Navigator
initialRouteName="Home"
<Tabs.Screen
name="Home"
component={HomeStack}
/>
Tabs.Screen
name="Settings"
component={SettingsStack}
children={this.SettingsStack}
</Tabs.Navigator>
)
}
const AuthStack = () => (
<AuthStack.Navigator>
<AuthStack.Screen
name="Auth"
component={Auth}
/>
</AuthStack.Navigator>
);
const SettingsStackScreen = () => (
<SettingsStack.Navigator>
<SettingsStack.Screen
name="Settings"
component={Settings}
/>
<SettingsStack.Screen
name="Privacy"
component={PrivacyStack}
/>
<SettingsStack.Screen
name="Theme"
component={ThemeScreen}
/>
<SettingsStack.Screen
name="Notifications"
component={NotificationsScreen}
/>
<SettingsStack.Screen
name="Sound"
component={SoundsScreen}
/>
</SettingsStack.Navigator>
);
const PrivacyStack = () => (
<PrivacyStack.Navigator>
<PrivacyStack.Screen
name="Privacy"
component={PrivacyScreen}
/>
<PrivacyStack.Screen
name="Notifications"
component={NotificationsScreen}
/>
</PrivacyStack.Navigator>
);
const App = () => {
return (
<NavigationContainer ref={navigationRef}>
<MainStack.Navigator>
<MainStack.Screen name="Tabs" component={TabNavigator} />
<MainStack.Screen
name="Auth"
component={AuthStack}
options={{gestureEnabled: false}}
/>
</MainStack.Navigator>
</NavigationContainer>
)
}
Settings.js File
import React, {Component} from 'react';
import {TouchableOpacity, ScrollView} from 'react-native;
import ClickableCard from './ClickableCard'
export default class Settings extends Component {
render(screen, index) {
return (
<ScrollView>
{ENTRIES.map((entry, index) => (
<ClickableCard screen={entry.screen} key={entry.index}/>
))}
</ScrollView>
)
}
export default Settings
ClickableCard.js Component
import React, {Component} from 'react';
import {TouchableOpacity, ScrollView} from 'react-native;
export default class ClickableCard extends Component {
constructor(props) {
super(props);
}
render() {
const {
screen,
key
} = this.props
return (
<TouchableOpacity
key={key}
onPress={() => this.props.navigation.navigate(screen)}>
</TouchableOpacity>
)
}
}
entries.js File
import React from 'react';
export const ENTRIES = [
{
name: "Theme",
screen: "ThemeScreen",
},
{
name: "Sounds",
screen: "SoundsScreen",
},
{
name: "Notifications",
screen: "NotificationsScreen",
},
]
You are trying to access navigation outside the navigation stack.
If you are using a functional component you can go with the useNavigation hook but as this is a class based component you will have to send the navigation as a prop or you can do the below as suggested in the documentation
import { useNavigation } from '#react-navigation/native';
class ClickableCard extends Component {
constructor(props) {
super(props);
}
render() {
const { screen, key } = this.props;
return (
<TouchableOpacity
key={key}
onPress={() =>
this.props.navigation.navigate(screen)
}></TouchableOpacity>
);
}
}
const ClickableCardWithNavigation= (props) {
const navigation = useNavigation();
return <ClickableCard {...props} navigation={navigation} />;
}
export default connect(ClickableCardWithNavigation)(TodoList)

React Native Navigation Component Not Rendering

I am using react navigation as per the docs but trying to make my app a bit more modular. I placed the result of createStackNavigator into a separate component..
Navigator.js
import React, { Component } from 'react';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import Home from './views/Home.js';
import TestComponent from './views/TestComponent.js';
const MainNavigator = createStackNavigator({
Home: {screen: Home},
Test: {screen: TestComponent}
});
export default createAppContainer(MainNavigator);
..and importing this component into my App.js
App.js
import React, { Component } from 'react';
import { View } from 'react-native';
import Header from './Header.js';
import Navigator from './Navigator.js';
import FooterMenu from './FooterMenu.js';
class App extends Component {
render() {
return (
<View>
<Header />
<Navigator />
<FooterMenu />
</View>
);
}
}
export default App;
My index.js is as follows:
import { AppRegistry } from 'react-native';
import App from './components/App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
Im finding that my <Header/> and <FooterMenu/> components are rendering but the <Navigator/> component is not.
I found that if I replace the top-level <View> component with a React fragment, it does render.
render() {
return (
<>
<Header />
<Navigator />
<FooterMenu />
</>
);
}
Although this syntax breaks my editor's (sublime) syntax highlighting. Though if I change the fragment to <React.Fragment> React native throws an exception.
My questions are:
Why does <Navigator/> not render if I wrap it in a <View> component?
Why do I get an error if I use <React.Fragment>?
If you want to create your own Navigator, here's how.
It is possible to take an existing Navigator and extend its behavior, using the following approach:
const MyStack = createStackNavigator({ ... });
class CustomNavigator extends React.Component {
static router = MyStack.router;
render() {
const { navigation } = this.props;
return <MyStack navigation={navigation} />;
}
}
Now it is possible to render additional things, observe the navigation prop, and override behavior of the router:
const MyStack = createStackNavigator({ ... });
class CustomNavigator extends React.Component {
static router = {
...MyStack.router,
getStateForAction: (action, lastState) => {
// check for custom actions and return a different navigation state.
return MyStack.router.getStateForAction(action, lastState);
},
};
componentDidUpdate(lastProps) {
// Navigation state has changed from lastProps.navigation.state to this.props.navigation.state
}
render() {
const { navigation } = this.props;
return (
<View>
<Header />
<MyStack navigation={navigation} />
<FooterMenu />
</View>
);
}
}
If you want to know more about this,

Categories

Resources