Cannot read property 'navigate' of undefined - javascript

full Login.js
'use strict'
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Image,
TouchableHighlight,
View,
Alert
} from 'react-native';
import { StackNavigator } from 'react-navigation'
class login extends Component{
static navigationOptions = {
title: 'Login'
}
render() {
return (
<View style={styles.contenedor} >
<Text style={styles.title}>La App chula</Text>
<TouchableHighlight style={styles.boton} onPress={(this.onLogin.bind(this))}>
<Text style={styles.letra}>Login</Text>
</TouchableHighlight>
</View>
);
}
onLogin = () => {
Alert.alert(
'Acceso',
'Te has logueado en el sistema',
[
{text: 'Aceptar',
onPress:(() => this.prop.navigation.navigate('Dashboard'))},
{text: 'Cancelar',
onPress:(this.cancelar.bind(this))}
]
)
}
cancelar(){
console.log(this.props)
}
}
const styles = StyleSheet.create({
contenedor:{
flex: 1,
/*justifyContent: 'center', /*Alineado Horizontalmente */
alignItems: 'center', /*Alineado Vertical*/
},
boton:{
backgroundColor: 'red',
alignItems: 'center',
justifyContent: 'center',
width: 300,
height: 30,
marginTop: 60,
marginBottom: 5,
borderRadius: 5,
},
letra:{
color: 'white',
},
title:{
fontSize: 25,
marginTop: 100,
},
});
module.exports = login
Hi I'm trying to learn React Native; I'm making an app native in IOS and i had this issue in Login.js when i was programming the navigator, anyone can help me? this is my code:
index.ios.js:
Configuration of StackNavigator
const IndexApp = StackNavigator({
Login: {screen: Login},
Dashboard: {screen: Dashboard}
in Login.js we have an alert; when you accept it takes you to the dashboard, we have first a navigationOptions in the login Component, we have other similar in Dashboard Component:
class login extends Component{
static navigationOptions = {
title: 'Login'
}
in the same file:
onLogin(){
Alert.alert(
'Acceso',
'Te has logueado en el sistema',
[
{text: 'Aceptar',
onPress:() => this.props.navigation.navigate('Dashboard')},
{text: 'Cancelar',
onPress:(this.cancelar.bind(this))}
]
)
}

Related

TypeError: undefined is not an object (evaluating '_this.submitTodo.bind') React Native App not working

I'm learning react native through a book and I was following the guide step by step. As I was coding and seeing the changes in the app I came across this error and I don't know what it means. I reviewed the code and compared with the code of the book and it's the same. I also searched the internet for some answers and couldn't find any. I'd be really glad if someone could tell me what I'm doing wrong here.
Here's the error I'm getting on the app:
The error in the windows terminal:
TypeError: undefined is not an object (evaluating '_this.submitTodo.bind')
This error is located at:
in App (at TodoApp/index.js:9)
in TodoApp (at renderApplication.js:50)
in RCTView (at View.js:32)
in View (at AppContainer.js:92)
in RCTView (at View.js:32)
in View (at AppContainer.js:119)
in AppContainer (at renderApplication.js:43)
in TodoApp(RootComponent) (at renderApplication.js:60)
Here's the App.js code:
import React, { Component } from 'react'
import { View, ScrollView, StyleSheet } from 'react-native'
import Heading from './Heading'
import Input from './Input'
import Button from './Button'
let todoIndex = 0
class App extends Component {
constructor() {
super()
this.state = {
inputValue: '',
todos: [],
type: 'All'
}
this.submitTodo = this.submitTodo.bind(this)
}
inputChange(inputValue) {
console.log(' Input Value: ' , inputValue)
this.setState({ inputValue })
}
sumbitTodo () {
if (this.state.inputValue.match(/^\s*$/)) {
return
}
const todo = {
title: this.state.inputValue,
todoIndex,
complete: false
}
todoIndex++
const todos = [...this.state.todos, todo]
this.setState({ todos, inputValue: '' }, () => {
console.log('State: ', this.state)
})
}
render () {
const { inputValue } = this.state
return (
<View style={styles.container}>
<ScrollView keyboardShouldPersistTaps='always' style={styles.content}>
<Heading />
<Input
inputValue={inputValue}
inputChange={ (text) => this.inputChange(text) } />
<Button submitTodo={this.submitTodo} />
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5'
},
content: {
flex: 1,
paddingTop: 60
}
})
export default App
Here's the Button.js code which might help:
import React from 'react'
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native'
const Button = ({ submitTodo }) => (
<View style={styles.buttonContainer}>
<TouchableHighlight
underlayColor='#efefef'
style={styles.button}
onPress={submitTodo}>
<Text style={styles.submit}>
Submit
</Text>
</TouchableHighlight>
</View>
)
const styles = StyleSheet.create({
buttonContainer: {
alignItems: 'flex-end'
},
button: {
height: 50,
paddingLeft: 20,
paddingRight: 20,
backgroundColor: '#ffffff',
width: 200,
marginRight: 20,
marginTop: 15,
borderWidth: 1,
borderColor: 'rgba(0,0,0,.1)',
justifyContent: 'center',
alignItems: 'center'
},
submit: {
color: '#666666',
fontWeight: '600'
}
})
export default Button
Here's the Input.js code which might help as well.
import React from 'react'
import { View, TextInput, StyleSheet } from 'react-native'
const Input = ({ inputValue, inputChange }) => (
<View style={styles.inputContainer}>
<TextInput
value={inputValue}
style={styles.input}
placeholder='What needs to be done?'
placeholderTextColor='#CACACA'
selectionColor='#666666'
onChangeText={inputChange} />
</View>
)
const styles = StyleSheet.create({
inputContainer: {
marginLeft: 20,
marginRight: 20,
shadowOpacity: 0.2,
shadowRadius: 3,
shadowColor: '#000000',
shadowOffset: { width: 2, height: 2 }
},
input: {
height: 60,
backgroundColor: '#ffffff',
paddingLeft: 10,
paddingRight: 10,
}
})
export default Input

How to navigate pages with React Navigator

Having trouble moving pages in React Navigator, it worked fine when we had homeStack and would just run through an object but now that we're trying to introduce a stationary button in the header that moves to another page it is running into problem. We still move just fine when we go from first to second page, but I think we're missing something.
OnPress is working when we press the folder icon as we console logged it, but it simply takes us back to our starting screen rather than to the screen we want to get to. I've tried to share the code needed but let me know if other pages are needed.
Below is our Header component, you can see where we're trying to onPress and then navigate.
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';
import {MaterialIcons} from '#expo/vector-icons';
import History from '../History'
import { NavigationContainer, StackActions } from "#react-navigation/native";
import { createNativeStackNavigator } from 'react-navigation-stack';
export default function Header({ navigation }){
const historyFolder = () => {
navigation.navigate('History')
}
return(
<View style={styles.header}>
<View>
<Text style={styles.headerText}></Text>
</View>
<MaterialIcons name='folder' size={28} onPress={historyFolder} style={styles.icon}></MaterialIcons>
</View>
)
}
const styles = StyleSheet.create({
header: {
width: '100%',
height: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
headerText: {
fontWeight: 'bold',
fontSize: 20,
color: '#333',
letterSpacing:1,
},
icon:{
position: 'absolute',
right: 16,
}
})
This is the History page that we're aiming to get to.
import { StyleSheet, Text, View, FlatList, SafeAreaView, Image } from 'react-native'
import Card from './shared/Card';
import React from 'react';
import { NavigationContainer, StackActions } from "#react-navigation/native";
import { createNativeStackNavigator } from 'react-navigation-stack';
export default function History({navigation}) {
const present = [{
id: 1,
name: 'PresentOne',
slug: 'PresentOne Slug',
image: require('../assets/present.jpeg')
},
{
id:2,
name: 'PresentTwo',
slug: 'PresentTwo Slug',
image: require('../assets/present2.jpeg')
},
{
id:3,
name: 'PresentThree',
slug: 'PresentThree Slug',
image: require('../assets/present3.jpeg')
},
{
id:4,
name: 'PresentFour',
slug: 'PresentFour Slug',
image: require('../assets/present4.jpeg')
},
{
id:5,
name: 'PresentFive',
slug: 'PresentFive Slug',
image: require('../assets/present5.jpeg')
},
];
const onePresent = ( { item } ) => (
<Card>
<View style={styles.item}>
<View style={styles.avatarContainer}>
<Image source = {item.image} style={styles.avatarContainer}/>
</View>
<Text style={styles.name}> {item.name}</Text>
<Text style={styles.slug}>{item.slug}</Text>
</View>
</Card>
)
const headerComponent = () => {
return <Text style={styles.listHeadline}>Presents</Text>
}
const itemSeperator = () => {
return <View style = {styles.seperator}/>
}
return (
<View>
<FlatList
ListHeaderComponentStyle={styles.listHeader}
ListHeaderComponent={headerComponent}
data = { present }
renderItem = { onePresent }
ItemSeperatorComponent = { itemSeperator }
ListEmptyComponent = { <Text>Empty</Text>}
/>
</View>
);
}
const styles = StyleSheet.create({
slug:{
transform: [{translateX: -100}],
// alignContent: 'center',
flexDirection: 'column',
alignItems: 'center',
},
name:{
transform: [{translateY: -30},{translateX: 10}],
fontSize: 20,
},
listHeadline:{
color:'#333',
fontSize: 21,
fontWeight: 'bold',
},
item: {
flex:1,
flexDirection:'row',
alignItems:'center',
paddingVertical:13,
},
avatarContainer:{
backgroundColor:'#D9D9D9',
borderRadius:100,
height:89,
width:89,
justifyContent:'center',
alignItems: 'center',
margin:10,
},
listHeader:{
height:55,
alignItems:'center',
justifyContent: 'center'
},
seperator: {
height: 1,
width: '100%',
backgroundColor: '#CCC',
}
})
And this is the homeStack we're running the page from.
import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import { createStackNavigator } from 'react-navigation-stack'
import { createAppContainer } from 'react-navigation'
import PositiveCollectForm from '../Components/PositiveCollectForm';
import NegativeCollectForm from '../Components/NegativeCollectForm';
import Swipe from '../Components/Swipe';
import History from '../Components/History';
import Header from '../Components/shared/Header';
const screens = {
PositiveCollectForm: {
screen: PositiveCollectForm,
navigationOptions: ({ navigation }) => {
return {
// headerTitle: () => <Header navigation={navigation} />
}
}
},
Swipe: {
screen: Swipe,
navigationOptions: {
title: '',
headerTitle: () => <Header navigation={navigation} />
},
},
History: {
screen: History,
navigationOptions: {
title: '',
headerStyle: {backgroundColor: '#555'}
}
},
}
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);

View config getter callback for component 'H' must be a function (received undefined)

Error is:
Invariant Violation: View config getter callback for component 'H' must be a function (received undefined)
I'm using react-native to make application and error happens when I clicked login button in MainLogin.js file. (It has to move to mainpage when clicking login button in login page)
I searched a lot but cannot know what is component 'H'.
attatched index.js (src/screens/index.js) and MainLogin.js (src/screens/MainLogin.js)
<index.js>
import React from 'react';
import {
Text
} from 'react-native';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createBottomTabNavigator } from "react-navigation-tabs";
import LoginScreen from './MainLogin';
import HomeScreen from './MainPage';
import DiaryScreen from './Diarymemo';
import StatScreen from './MoodStatistics';
import CommuScreen from './Community';
import StoreScreen from './Store';
const HomeStack = createStackNavigator(
{
HomeScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Home'}),
}
);
const DiaryStack = createStackNavigator(
{
DiaryScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Diary'}),
}
);
const StatStack = createStackNavigator(
{
StatScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Stat'}),
}
);
const CommunityStack = createStackNavigator(
{
CommuScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Network'}),
}
);
const StoreStack = createStackNavigator(
{
StoreScreen
},
{ defaultNavigationOptions : ({navigation}) => ({
title: 'Store'}),
}
);
const TabNavigator = createBottomTabNavigator(
InitialRouteName = 'Home',
{
Diary: DiaryStack,
Stat: StatStack,
Home: HomeStack,
Network: CommunityStack,
Store: StoreStack,
},
{
defaultNavigationOptions: ({navigation}) => ({
tabBarIcon: ({focused, horizontal, tintColor}) => {
const {routeName} = navigation.state;
let icon = "▲";
if(routeName === 'Diary'){
icon = "📓";
} else if(routeName === 'Stat'){
icon = "📊"
} else if(routeName === 'Home'){
icon = "🍎"
} else if(routeName === 'Network'){
icon = "👫"
} else if(routeName === 'Store'){
icon = "🛍"
}
// can use react-native-vector-icons
// <Icon name={iconName} size={iconSize} color={iconColor} />
return <Text style={{color: focused && "#46c3ad" || "#888"}}>{icon}</Text>
}
}),
lazy: false,
tabBarOptions: {
activeTintColor: "#46c3ad",
inactiveTintColor: "#888",
},
}
);
const AppStack = createStackNavigator(
{
LoginScreen: LoginScreen,
TabNavigator: {
screen: TabNavigator,
navigationOptions: ({navigation}) => ({
headerShown: false,
}),
},
}
);
export default createAppContainer(AppStack);
<MainLogin.js>
import React, {Component} from 'react';
import {
View,
Text,
TextInput,
TouchableOpacity,
StyleSheet
} from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
export default class LoginScreen extends Component{
static navigationOptions = {
headerShown: false,
};
_doLogin(){
// do something
this.props.navigation.replace('TabNavigator')
}
render(){
return (
<View style={styles.container}>
<View style={styles.titleArea}>
<Text style={styles.title}>MoodiBuddy</Text>
</View>
<View style={styles.formArea}>
<TextInput
style={styles.textForm}
placeholder={"ID"}/>
<TextInput
style={styles.textForm}
placeholder={"Password"}/>
</View>
<View style={styles.buttonArea}>
<TouchableOpacity
style={styles.button}
onPress={this._doLogin.bind(this)}>
<Text style={styles.buttonTitle}>Login</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
paddingLeft: wp('10%'),
paddingRight: wp('10%'),
justifyContent: 'center',
},
titleArea: {
width: '100%',
padding: wp('10%'),
alignItems: 'center',
},
title: {
fontSize: wp('10%'),
},
formArea: {
width: '100%',
paddingBottom: wp('10%'),
},
textForm: {
borderWidth: 0.5,
borderColor: '#888',
width: '100%',
height: hp('5%'),
paddingLeft: 5,
paddingRight: 5,
marginBottom: 5,
},
buttonArea: {
width: '100%',
height: hp('5%'),
},
button: {
backgroundColor: "#46c3ad",
width: "100%",
height: "100%",
justifyContent: 'center',
alignItems: 'center',
},
buttonTitle: {
color: 'white',
},
})

How to re-render a tab in React-Native

I have a React-Native flashcard app that boots with two tabs, a Home tab, and a New Deck tab. The Home tab is the default, and you can press or swipe over to the New Deck tab.
The Home tab displays all of the decks the user currently has saved.
On the New Deck tab, I have the user enter the title of their new deck and press a submit button. When that submit button is pressed, I re-navigate to the Home tab.
My issue is: How in the world do I trigger a re-render on the Home tab from a button press on the New Deck tab so the user can see the deck they just created?
I know I could use Redux to solve this issue, but no other part of the app is optimized in a "Redux" fashion, and I'd really like to not redesign the architecture of my app for the sole purpose of updating a single screen, mostly because this is the only instance where I would need this ability.
I've attempted to get around this by passing screenProps containing the this.forceUpdate method all the way from the StackNavigator component, but it didn't work. I also tried manually update the state of the App component to trigger a re-render, but the re-render never happened (although the state did update).
App.js
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import AlphaHome from './Components/Home/AlphaHome'
import AlphaQuiz from './Components/Quiz/AlphaQuiz'
import AlphaNewUdaciDeck from './Components/NewUdaciDeck/AlphaNewUdaciDeck'
import AlphaNewUdaciCard from './Components/NewUdaciCard/AlphaNewUdaciCard'
import AlphaUdaciDeckDetails from './Components/UdaciDeckDetails/AlphaUdaciDeckDetails'
import { TabNavigator, StackNavigator } from 'react-navigation'
const Tabs = TabNavigator({
Home: {
screen: AlphaHome,
navigationOptions: {
tabBarLabel: 'Home',
},
},
NewDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
tabBarLabel: 'New Deck',
}
}
}, {
navigationOptions: {
header: null,
},
tabBarOptions: {
activeTintColor: 'white',
indicatorStyle: {
backgroundColor: 'white'
},
style: {
height: 50,
borderBottomColor: 'white',
backgroundColor: 'deepskyblue',
}
},
})
const Stack = StackNavigator({
Home: {
screen: Tabs,
},
AlphaNewUdaciDeck: {
screen: AlphaNewUdaciDeck,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaNewUdaciCard: {
screen: AlphaNewUdaciCard,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
AlphaUdaciDeckDetails: {
screen: AlphaUdaciDeckDetails,
navigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: 'deepskyblue'
}
}
},
})
export default class App extends Component {
render() {
return (
<Stack />
)
}
}
Home.js
import React, { Component } from 'react'
import { ScrollView, View, Text, StyleSheet, AsyncStorage, ActivityIndicator } from 'react-native'
import UdaciDeck from '../Reusable/UdaciDeck'
import { getAllData } from '../../utils/AsyncApi'
export default class HomeExistingUser extends Component {
state = {
decks: null,
}
componentDidMount() {
let decks = getAllData()
setTimeout(() => {
this.setState({
decks
})
}, 1000)
}
showDetails = (title, count) => {
this.props.navigation.navigate('AlphaUdaciDeckDetails', {title, count})
}
render() {
const {decks} = this.state
return (
decks
? <ScrollView contentContainerStyle={styles.container}>
{decks.map(s => <UdaciDeck key={s[1].title} name={s[1].title} count={s[1].questions.length} method={this.showDetails} />)}
</ScrollView>
: <View style={[styles.container, {flex: 1, justifyContent: 'center'}]}>
<ActivityIndicator size='large' color='white' />
</View>
)
}
}
const styles = StyleSheet.create({
container: {
minHeight: '100%',
backgroundColor: 'lightskyblue',
paddingTop: 20,
paddingBottom: 20,
alignItems: 'center',
},
})
NewDeck.js
import React, { Component } from 'react'
import { View, Text, TextInput, StyleSheet, AsyncStorage, TouchableNativeFeedback, Alert } from 'react-native'
import { addDeck } from '../../utils/AsyncApi'
// BUG: when adding a new deck (if HomeExistingUser is true) view doesn't update. Need to figure out a way to update on tab navigate back
export default class AlphaNewUdaciDeck extends Component {
state = {
input: '',
keys: null,
}
componentDidMount() {
AsyncStorage.getAllKeys()
.then(keys => this.setState({
keys
}))
}
handleSubmit = () => {
const {input, keys} = this.state
input.search(' ') > 0 || input.length < 1 || keys.filter(s => s === input).length > 0
? Alert.alert(`Please enter a valid name (${input.length < 1 || keys.filter(s => s === input).length > 0 ? `you can't save a deck with ${input.length < 1 ? 'no' : 'an already used'} name` : "no spaces"})`)
: addDeck(input)
;if(input.search(' ') < 0 || input.length > 0 || keys.filter(s => s === input).length < 1) {
this.props.navigation.goBack()
}
}
render() {
return (
<View style={[styles.container, styles.containerOne]}>
<View style={styles.containerTwo}>
<Text style={styles.text}>Name of the deck</Text>
<Text style={styles.text}>(Please no spaces)</Text>
<TextInput
autoFocus={true}
onChangeText={(input) => this.setState({
input
})}
selectionColor={'deepskyblue'}
underlineColorAndroid={'transparent'}
style={styles.input}
/>
<TouchableNativeFeedback onPress={this.handleSubmit}>
<View style={styles.btn}>
<Text style={styles.btnText}>Save Deck</Text>
</View>
</TouchableNativeFeedback>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'lightskyblue',
},
containerOne: {
alignItems: 'center',
},
containerTwo: {
marginTop: 50,
},
text: {
color: 'white',
fontSize: 20,
},
input: {
backgroundColor: 'white',
height: 50,
width: 300,
marginTop: 15,
fontSize: 20,
paddingLeft: 5,
paddingRight: 5,
color: 'deepskyblue'
},
btn: {
backgroundColor: 'deepskyblue',
marginTop: 50,
padding: 20,
paddingLeft: 50,
paddingRight: 50,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
},
btnText: {
color: 'white',
},
})
You should check out react-navigation-is-focused-hoc at https://github.com/pmachowski/react-navigation-is-focused-hoc to solve the specific problem you mentioned.
You can also try
onNavigationStateChange(prevState, newState)
there is a sample at How can I tell if the screen is navigated to with ReactNavigation

understanding "undefined is not an object('this.props.navigation.navigate)"

I am getting the error "undefined is not an object('this.props.navigation.navigate)" when I click the button titled with "Chat with Lucy" which is supposed to take me to the ChatScreen screen.
All of this code is within the App.js file i'm using that is being exported into the android and ios files.
Any reason why i'm getting this error? thanks!
import React, { Component } from 'react';
import { StackNavigator } from 'react-navigation';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
Button
} from 'react-native';
export default class firstapp extends Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Image source={require('./Packit_title.png')} />
<TextInput
style={styles.account}
/>
<TextInput
style={styles.account}
/>
<View style={styles.button}>
<Button
title="Login"
color="#c47735"
/>
<Button
title="Sign Up"
color="#c47735"
/>
</View>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
class ChatScreen extends Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text>Chat with Lucy</Text>
</View>
);
}
}
const firstappNav = StackNavigator({
Home: { screen: firstapp },
Chat: { screen: ChatScreen },
});
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#f49542',
},
account: {
backgroundColor: '#ffffff',
height: 40,
borderColor: 'gray',
borderWidth: 1,
marginBottom: 10,
width: 200
},
button: {
flexDirection: 'row',
}
});
AppRegistry.registerComponent('firstapp', () => firstapp);
You are exporting your firstapp component which has no access to the navigation prop since nothing is being passed to it. You need to export your navigator component firstappNav instead.
AppRegistry.registerComponent('firstapp', () => firstappNav);
This is because props object is undefined in firstapp Component. You will have to override its constructor to access props. Read this

Categories

Resources