this.props in component does not contain navigation property - reactjs

I want to navigate from one screen to another by this.props.navigation.navigate('Second Screen') but property 'navigation' does not contain in the props. Get error:
Property 'navigation' does not exist on type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>'
import React, { Component } from "react";
import styles from "./style";
import { Keyboard, Text, View, TextInput, TouchableWithoutFeedback, KeyboardAvoidingView } from 'react-native';
import { Button } from 'react-native-elements';
export default class SignInScreen extends Component {
render() {
return (
<KeyboardAvoidingView style={styles.containerView} behavior="padding">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.loginScreenContainer}>
<View style={styles.loginFormView}>
<Text style={styles.logoText}>Book Market</Text>
<TextInput placeholder="Email" placeholderTextColor="#c4c3cb" style={styles.loginFormTextInput} />
<TextInput placeholder="Password" placeholderTextColor="#c4c3cb" style={styles.loginFormTextInput} secureTextEntry={true} />
<Button
buttonStyle={styles.loginButton}
onPress={this.props.navigation.navigate('Home')}
title="Login"
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
}
}

You can only access it through the parent element. Pass navigation as a prop to its children to use it
Eg:
<Child navigation={this.props.navigation} />

You can do what was already suggested, pass the navigation prop down to your target component
Ex:
<TargetComponent navigation={this.props.navigation} />
Or you can use withNavigation HOC from react-natigation.
Ex:
import {withNavigation} from 'react-navigation'
...
export default withNavigation(Child)
Hope it helps.

Okay, I find a solution. At first, I need to change extends of my class like
export default class SignInScreen extends Component<{navigation: any}>
Then change onPress action:
<Button
buttonStyle={styles.loginButton}
onPress={() => this.onSignInPress()}
title="Login"
/>
private onSignInPress() {
this.props.navigation.navigate('Home');
}

I know this is an old question, but since the problem of undefined navigation property still exists at least for those who use EXPO managed approach, I'll write my solution hopefully it'll save someone's day.
After searching for hours I found no way to fix this bug and find a way to add navigation property to this.props. Finally, I solved the problem by using NavigationContext in this way:
<NavigationContainer>
<NavigationContext.Provider>
<Stack.Navigator>
...
</Stack.Navigator>
</NavigationContext.Provider>
</NavigationContainer>
Then get the navigation in a consumer:
<NavigationContext.Consumer>
{navigation => {
return (
<Button onPress={() => this.onButtonPress(navigation)} />
);
}}
</NavigationContext.Consumer>
And finally:
onButtonPress(navigation) {
try {
navigation.navigate(RouteNames.FORGOTTEN_PASSWORD_SCREEN);
} catch (e) {
this.setState({ errors: [e.message] });
}
}

Related

Anybody know why this doesn't work if its writen like the react navigation docs?

This is the btn that 'controls' the navigation.
It loads the first Stack, Home, but when I press the touchable opacity to go QnScreen it drops an error: undefined is not an object (evaluating 'navigation.navigate').
I try it all, I'm falling into depression lol.
import * as React from 'react';
import { LinearGradient } from "expo-linear-gradient";
import { StyleSheet, Text, TouchableOpacity, Image } from "react-native";
export default function DocCard( { navigation } ){
return(
<TouchableOpacity
style={styles.container}
onPress={()=>{
navigation.navigate('QnScreen')
}}
>
<LinearGradient
style={styles.linearGradient}
colors={['#4822E4','transparent']}
start={{x:0, y:0}}
end={{x:1, y:1}}>
<Text style={styles.title}>Create new Doc.</Text>
<Image
style={styles.icon}
source={require('../../img/HomeScreen/doc_icon.png')}
/>
</LinearGradient>
</TouchableOpacity>
);
}
And this is the MainStack:
import { NavigationContainer, useNavigation } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import QnScreen from '../screens/QnScreen';
import Home from '../screens/Home';
import React from 'react';
const Stack = createNativeStackNavigator();
export default function MainStack(){
return(
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false
}}
>
<Stack.Screen
name='Home'
component={Home}
/>
<Stack.Screen
name='QnScreen'
component={QnScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
I'm using Expo with typescript
First off, you'll need to have that navigation.navigate() call include a parameter that states which screen/screen-stack you want to navigate to. It doesn't look like that's your main issue though.
I can't tell from just the code you've posted, but judging from the 'navigation' object being undefined, it's most likely that your DocCard component is not a child of your Navigator. Where is DocCard in your component tree? Is it inside QnScreen or Home? Cause that's where it should be.
Then you'll need to receive the 'navigation' prop from one of your screens. And pass it as a prop to DocCard to be used. 'Navigation' and 'route' props are only automatically passed to screens.
I solve it!!!
The solution was using the useNavigation hook inside the component.
import { useNavigation } from "#react-navigation/native";
import { LinearGradient } from "expo-linear-gradient";
import { StyleSheet, Text, TouchableOpacity, Image } from "react-native";
export default function DocCard(){
const navigation = useNavigation();
return(
<TouchableOpacity
style={styles.container}
onPress={()=>{
navigation.navigate('QnScreen');
}}
>
<LinearGradient
style={styles.linearGradient}
colors={['#4822E4','transparent']}
start={{x:0, y:0}}
end={{x:1, y:1}}>
<Text style={styles.title}>Crear nuevo documento de consentimiento informado.</Text>
<Image
style={styles.icon}
source={require('../../img/HomeScreen/doc_icon.png')}
/>
</LinearGradient>
</TouchableOpacity>
);
}
If anybody have this problem, there's the solution:)

React navigation drawer content props types definition

I am creating a custom drawer content using this guide:
const DrawerContent = (props) => (
<DrawerContentScrollView {...props}>
<AntDesign
name="close"
size={32}
onPress={() => props.navigation.closeDrawer()}
/>
<Text>TEST</Text>
<DrawerItemList {...props} />
</DrawerContentScrollView>
);
It works well, but I would like type checking on the props parameter. So I tried:
import { DrawerContentComponentProps } from '#react-navigation/drawer';
const DrawerContent = (props: DrawerContentComponentProps) => (
// Same stuff
);
But my IDE is now telling me that props.navigation.closeDrawer does not exist, but it does.
What is the correct way to define the props type of the DrawerContent function?
This is a know issue of react-navigation library: https://github.com/react-navigation/react-navigation/issues/6790
In order to make the warning disappear waiting the fix, you can use this notation:
import { DrawerActions } from '#react-navigation/native';
<AntDesign
name="close"
size={32}
// #see https://github.com/react-navigation/react-navigation/issues/6790
onPress={() => navigation.dispatch(DrawerActions.closeDrawer())}
/>

(React-Native) undefined is not an object (evaluating _'this.props.navigation.navigate')

I'm still a novice with react. I want to make my sign In button create a new screen on the press. I've tried multiple attempts but I can't seem to get past this error:
What is it I'm doing wrong?
LoginForm.js:
import React, { Component } from 'react';
import { TextInput, Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import { StackNavigator } from 'react-navigation';
import { Button, CardSection, Input, Spinner } from './common';
import Account from './screens/Account';
import SignUpForm from './SignUpForm';
class LoginForm extends Component {
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Username or email"
placeholderTextColor='white'
returnKeyType='next'
style={styles.input}
keyboardType="email-address"
onSubmitEditing={() => this.passwordInput.focus()}
/>
<TextInput
secureTextEntry //turns text into *** good for passwords
label="Password"
placeholder="password"
placeholderTextColor='white'
secureTextEntry
returnKeyType='go'
style={styles.input}
ref={(input) => this.passwordInput = input}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>LOGIN</Text>
</TouchableOpacity>
<Text style={styles.textStyle}> Need help logging in?{'\n'}
or
</Text>
<View style={styles.divider} />
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('SignUpForm')}
>
<Text style={styles.buttonText}>Sign Up</Text>
</TouchableOpacity>
</View>
);
}
}
export default LoginForm;
**Account.js:**
import React from 'react';
import { View, Image, TouchableOpacity, Text, TextInput } from 'react-native';
import { StackNavigator } from 'react-navigation';
import { Card, Button, Spinner, CardSection } from '../common';
import LoginForm from '../LoginForm';
class Account extends React.Component {
static navigationOptions = {
tabBarLabel: 'Account'
}
render() {
return (<View style={styles.containerStyle}>
<Card>
<View style={styles.logoContainer}>
<Image style={styles.logo} source= .
{require('../../Images/ShoeJackCityLogo.png')}/>
</View>
<View style={styles.formContainer}>
<LoginForm />
</View>
</Card>
</View>);
}
}
export default Account;
**SignUpForm.js:**
import React, { Component } from 'react';
import { TextInput, Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import { Button, CardSection, Input, Spinner } from './common';
import router from '../../config/router';
class SignUpForm extends Component {
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Username or email"
placeholderTextColor='white'
returnKeyType='next'
style={styles.input}
keyboardType="email-address"
onSubmitEditing={() => this.EmailInput.focus()}
/>
<TextInput
placeholder="Email"
placeholderTextColor='white'
returnKeyType='next'
style={styles.input}
keyboardType="email-address"
onSubmitEditing={() => this.passwordInput.focus()}
/>
<TextInput
secureTextEntry //turns text into *** good for passwords
label="Password"
placeholder="password"
placeholderTextColor='white'
secureTextEntry
returnKeyType='go'
style={styles.input}
ref={(input) => this.passwordInput = input}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>Register</Text>
</TouchableOpacity>
</View>
);
}
}
export default SignUp;
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
**Router.js**
import Tournaments from '../components/screens/Tournaments';
import Account from '../components/screens/Account';
import Artists from '../components/screens/Artists';
import Shop from '../components/screens/Shop';
import SignUpForm from '../components/SignUpForm';
export const AccountStack = StackNavigator({
Account: {
screen: Account,
navigationOptions: {
title: 'Account',
headerBackTitle: null,
},
SignUpForm: {
screen: SignUpForm,
navigationOptions: {
title: 'Register'
}
},
Ignore this: jsksjkjdkfjkdfkjkdjskfjskjfjksjkjfkjsjfkjskfsjfjsjfksjfjfskfjkskjfjkjskjfjjksfjksfjkfjkfjssfjkfksskjfjsfjk
<LoginForm />
I don't see that you are passing any props into LoginForm which expects this.props.navigation in onPress.
I think you have some confusion related to how the navigation stack works in react-native. So, essentially there are two ways of navigating to a screen.
By declaring it in the StackNavigator class, you are providing the <LoginForm/> component the required navigation object. Once, declared you'll need to navigate to the login form from any screen - like - this.props.navigation.navigate('LoginForm'). Note - you'll be only be able to navigate from either <Account/> or <Signup/> because those two screens currently posses the navigation object in their scope. Now, once you have navigated to the login form component you'll essentially have the navigation object in scope, and your undefined error will go away.
If you decide not to declare the <LoginForm/> screen in the StackNavigator class, you'll need to pass the navigation object explicitly as props to the component, like - <LoginForm navigation={this.props.navigation} />. So, that whenever you render this component, you'll be able to fetch the navigation prop the same way you are using it.
Hope it clears out things for you :)
Its hard for me to tell without seeing where you declared your stafcknavigation if you didn't then this is the link to learn how http://react-navigation%20stack%20navigator%20custom%20header
otherwhise you are probably not passing the navigation method to a nested component
here is a link to see how to do that navigation between component in react native
Your LoginForm component doesn't have 'this.props.navigate' since it is not registered with any navigator, you are calling that component inside your 'Account' component which is registered to navigator.
If you want to navigate inside 'LoginForm' you need to pass 'this.props.navigation' like
<LoginForm myNavigation = {this.props.navigation} />
And inside that onPress in LoginForm use
onPress = { ()=> this.props.myNavigation.navigate('SignUpForm) }

React Native : Custom Tabbar

React native : How can I custom tab bar like image below??
1) you can use this library to create tabs react-native-scrollable-tab-view.
2) Then it has a prop (renderTabBar) here you can pass your own custom tab bar.
<ScrollableTabView renderTabBar={() => <DefaultTabBar tabStyle={{color: 'red'}} />} />
one tip that i am giving.
make a file name it CustomTabBar copy all the code from libraries DefaultTabBar and past it in your CustomTabBar.
now change its designs the way you want it to be and use it like this. This way you will have to do the least amount of work.
<ScrollableTabView renderTabBar={() => <CustomTabBar/>} />
Maybe this is the solution you need
1, Install: switch-react-native
npm i switch-react-native
2, Using lib:
import React, { Component } from 'react';
import { View } from 'react-native';
import { Switch } from 'switch-react-native';
class SwitchExample extends Component {
render() {
return (
<View>
<Switch
height={40}
width={300}
activeText={`Active Text`}
inActiveText={`InActive Text`}
onValueChange={(value: any) => console.log(value)}
/>
</View>
);
}
}

React Native What I'm doing wrong here with constant

I'm trying to implement one functional component. Here I am doing below, But I'm getting error about props. Could someone help me.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const TextField = () => {
return (
<Text> {this.props.title} </Text>
)
}
export default TextField;
// APP Component
import TextField from './Components/TextField'
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<TextField title= "Simple App"/>
</View>
);
}
}
The reason is this.props is not defined in a functional component. They receive the props as an argument.
Change your TextField to take argument props and use props.title
const TextField = (props) => {
return (
<Text> {props.title} </Text>
)
}

Resources