react-native: `this.state` is undefined in login function - javascript

I'm having trouble accessing this.state in functions inside my component.
Always I get "Undefined is not a object this.state.username, this.state.password" error
SimpleForm.js
import Expo from 'expo';
import React from 'react';
import { StackNavigator, DrawerNavigator } from 'react-navigation';
import App from './App';
import RegisterForm from './register';
import { View, Text, TextInput, Image, TouchableOpacity, AsyncStorage, StyleSheet } from 'react-native';
import { YourRestApi } from './constants/api3';
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.state = { username: '', password: '', datas: '' };
this.login = this.login.bind(this, this.state.username, this.state.password);
}
componentWillMount() {
this.login();
}
registerscreen = () => {
this.props.navigation.navigate('Register');
}
login() {
YourRestApi(this.state.username, this.state.password)
.then((response) => {
console.log(response.success);
this.setState({ loading: false, datas: response });
});
if (this.state.datas.success === true) {
const info = this.state.datas.message;
AsyncStorage.setItem('info', JSON.stringify(info));
this.props.navigation.navigate('SecondScreen');
} else {
alert(this.state.datas.message);
}
}
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<Image source={require('./assets/img/sd.png')} style={styles.backgroundImage}>
<View style={styles.content}>
<Text style={styles.logo}>Toto Prediction </Text>
<View style={styles.inputContainer}>
<TextInput
underlineColorAndroid='transparent' style={styles.input}
onChangeText={(username) => this.setState({ username })}
value={this.state.username} placeholder='username'
/>
<TextInput
secureTextEntry underlineColorAndroid='transparent' style={styles.input}
onChangeText={(password) => this.setState({ password })}
value={this.state.password} placeholder='password'
/>
</View>
<TouchableOpacity onPress={this.login} style={styles.buttonContainer}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
this._onPressGet.bind(this)
<TouchableOpacity onPress={this.registerscreen} style={styles.buttonContainer}>
<Text style={styles.buttonText}>Register</Text>
</TouchableOpacity>
</View>
</Image>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
backgroundImage: {
flex: 1,
alignSelf: 'stretch',
width: null,
justifyContent: 'center',
},
content: {
alignItems: 'center',
},
logo: {
color: 'white',
fontSize: 40,
fontStyle: 'italic',
fontWeight: 'bold',
textShadowColor: '#252525',
textShadowOffset: { width: 2, height: 2 },
textShadowRadius: 15,
marginBottom: 20,
},
inputContainer: {
margin: 20,
marginBottom: 0,
padding: 20,
paddingBottom: 10,
alignSelf: 'stretch',
borderWidth: 1,
borderColor: '#fff',
backgroundColor: 'rgba(255,255,255,0.2)',
},
input: {
fontSize: 16,
height: 40,
padding: 10,
marginBottom: 10,
backgroundColor: 'rgba(255,255,255,1)',
},
buttonContainer: {
margin: 20,
padding: 20,
backgroundColor: 'blue',
borderWidth: 1,
borderColor: '#fff',
backgroundColor: 'rgba(255,255,255,0.6)',
},
buttonText: {
fontSize: 16,
fontWeight: 'bold',
textAlign: 'center',
},
});
const SimpleApp = DrawerNavigator({
Onescreen: { screen: SimpleForm },
SecondScreen: { screen: App },
Register: { screen: RegisterForm },
});
Expo.registerRootComponent(SimpleApp);
Api3.js
export function YourRestApi(username1, password1) {
fetchlogin(username1, password1);
}
function fetchlogin(username1, password1) {
const details = {
username: username1,
password: password1,
};
const formBody = Object.keys(details).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(details[key])}`).join('&');
fetch('https://*********************', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formBody,
})
.then((response) => response.json())
.then((response) => {
console.log('requestAppInstallation success ', response);
return response;
})
.done();
}
I tried binding login to this.state but doesnt worked
I already checked other questions but nothing is worked
Any idea what could be causing this ?

In your constructor replace the binding statement like below
constructor(props) {
super(props);
this.state = { username: '', password: '', datas: '' };
this.login = this.login.bind(this);
}

Your login function should be bound in order for it to access the correct this if passed to a Touchable.
Could be fixed by either one of these ways:
<TouchableOpacity onPress={this.login.bind(this)} ...>
OR:
<TouchableOpacity onPress={() => this.login()} ...>

It is basically nothing but just an error returned by firebase in case user enters wrongly formatted email. Try entering rightly formatted email id in the signup or login form and you will not get that error from firebase.
Firebase basically checks at its end whether user entered correct mail id or not while creating new user.

Related

React Native and Firebase Real Time Database

I am having 2 problems using React Native and Firebase Real Time Database.
When I add something to the list with the text input, all the list itens are duplicated except the item that I just added, this problem is only solved when I refresh the app screen.
When I remove something from firebase dashboard or other client, the list is not updated real time.
import React, {useState, Component} from 'react';
import {
Text,
View,
Switch,
StyleSheet,
FlatList,
TextInput,
Button,
TouchableOpacity,
SafeAreaView,
VirtualizedList,
} from 'react-native';
import database from '#react-native-firebase/database';
class MenuBreakFastScreen extends React.Component {
state = {newItem: ''};
state = {itens: []};
componentDidMount() {
let dbRef = database().ref('/cafe/itens/');
this.listenerFirebase(dbRef);
}
listenerFirebase(dbRef) {
dbRef.on('value', dataSnapshot => {
const newItens = JSON.parse(JSON.stringify(this.state.itens));
dataSnapshot.forEach(child => {
newItens.push({
name: child.val().name,
key: child.key,
});
this.setState({itens:newItens});
});
});
}
addItem() {
if (this.state.newItem === '') {
return;
}
database().ref('/cafe/itens/').push({
name: this.state.newItem,
});
this.setState({
newItem: '',
});
}
render() {
const {itens} = this.state;
const {newItem} = this.state;
const renderItem = ( {item}) => {
return(
<ItemAsset title={item.name}/>
);
}
return (
<SafeAreaView
style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<FlatList
data={itens}
renderItem={renderItem}
keyExtractor={item => item.key}
/>
<SafeAreaView style={{flexDirection: 'row'}}>
<TextInput
style={styles.input}
onChangeText={text =>
this.setState({
newItem: text,
})
}
value={newItem}
/>
<TouchableOpacity style={styles.Botao} onPress={() => this.addItem()}>
<Text style={styles.BotaoTexto}>+</Text>
</TouchableOpacity>
</SafeAreaView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
texto: {
fontSize: 35,
},
input: {
color: '#000',
fontSize: 22,
borderWidth: 1,
flex: 8,
margin: 10,
},
BotaoTexto: {
color: '#fff',
fontSize: 22,
},
Botao: {
backgroundColor: '#000',
marginTop: 10,
padding: 10,
flex: 1,
alignItems: 'center',
margin: 10,
},
ListaContainer: {
flexDirection: 'row',
backgroundColor: '#000',
flex: 1,
},
item: {
backgroundColor: '#000',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
flexDirection: 'row',
},
title: {
color: '#ffff',
fontSize: 32,
},
});
const ItemAsset = ( {title} ) => {
return(
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
}
export default MenuBreakFastScreen;
When you are listen for real time changes on real-time database it will send all the items with snapshot when any data is changed. That happens because you are listen for whole list, not only for a single item. Therefore you do not need to get the current list from state. You just have to set the state with retrieved data.
listenerFirebase(dbRef) {
dbRef.on('value', dataSnapshot => {
const newItens = []; // This should be initially empty array. That's all.
dataSnapshot.forEach(child => {
newItens.push({
name: child.val().name,
key: child.key,
});
});
this.setState({itens:newItens});
});
}
After correcting this part the error you got when removing data will be also resolved.

TypeError: TypeError: undefined is not an object (evaluating 'this.props.navigation.state.params.name')

I know there have been similar questions, but I tried anyway and still can't find the solution.
I have a login screen, registration, chat and a test screen (where I use just to try to fix this error) I want to pass the name, email and avatar data that I get there from Login / Register, but it is returned to me that the object is undefined. I only corrected the error if I put the navigation as follows: Login or Register> Chat. However, I do not want to do so, I need to click on an image and direct to this chat. Apparently it's a common mistake, but I'm frustrated with trying to fix it (I'm new to React-Native)
Chat.js
import { GiftedChat } from "react-native-gifted-chat"; // 0.3.0
import firebaseSvc from "../FirebaseSvc";
type Props = {
name?: string,
email?: string,
avatar?: string
};
class Chat extends React.Component<Props> {
constructor(props) {
super(props);
}
static navigationOptions = ({ navigation }) => ({
title: (navigation.state.params || {}).name || "Chat!"
});
state = {
messages: []
};
get user() {
return {
name: this.props.navigation.state.params.name,
email: this.props.navigation.state.params.email,
avatar: this.props.navigation.state.params.avatar,
id: firebaseSvc.uid,
_id: firebaseSvc.uid // need for gifted-chat
};
}
render() {
return (
<GiftedChat
messages={this.state.messages}
onSend={firebaseSvc.send}
user={this.user}
/>
);
}
componentDidMount() {
firebaseSvc.refOn(message =>
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, message)
}))
);
}
componentWillUnmount() {
firebaseSvc.refOff();
}
}
export default Chat;
Login.js
import { Constants, ImagePicker, Permissions } from "expo";
import {
StyleSheet,
Text,
TextInput,
TouchableOpacity,
KeyboardAvoidingView,
View,
Button,
ImageEditor,
Image,
StatusBar,
LayoutAnimation
} from "react-native";
import firebaseSvc from "../FirebaseSvc";
import firebase from "firebase";
import { auth, initializeApp, storage } from "firebase";
import uuid from "uuid";
class Login extends React.Component {
state = {
name: "",
email: "",
password: "",
avatar: ""
};
// using Fire.js
onPressLogin = async () => {
console.log("pressing login... email:" + this.state.email);
const user = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
avatar: this.state.avatar
};
const response = firebaseSvc.login(
user,
this.loginSuccess,
this.loginFailed
);
};
loginSuccess = () => {
console.log("login successful, navigate to chat.");
this.props.navigation.navigate("TelaTeste", {
name: this.state.name,
email: this.state.email,
avatar: this.state.avatar
});
};
loginFailed = () => {
console.log("login failed ***");
alert("Login failure. Please tried again.");
};
onChangeTextEmail = email => this.setState({ email });
onChangeTextPassword = password => this.setState({ password });
render() {
LayoutAnimation.easeInEaseOut();
return (
<View style={styles.container}>
<KeyboardAvoidingView behavior="padding">
<Text style={styles.titulo}>{"CUDDLE"}</Text>
<View style={styles.errorMessage}>
{this.state.errorMessage && (
<Text style={styles.error}>{this.state.errorMessage}</Text>
)}
</View>
<View style={styles.form}>
<View>
<Text style={styles.inputTitle}>Email Address</Text>
<TextInput
style={styles.input}
autoCapitalize="none"
onChangeText={this.onChangeTextEmail}
value={this.state.email}
></TextInput>
</View>
<View style={{ marginTop: 32 }}>
<Text style={styles.inputTitle}>Password</Text>
<TextInput
style={styles.input}
secureTextEntry
autoCapitalize="none"
onChangeText={this.onChangeTextPassword}
value={this.state.password}
></TextInput>
</View>
</View>
<TouchableOpacity style={styles.button} onPress={this.onPressLogin}>
<Text style={{ color: "#FFF", fontWeight: "500" }}>Sign in</Text>
</TouchableOpacity>
<TouchableOpacity
style={{ alignSelf: "center", marginTop: 32 }}
onPress={() => this.props.navigation.navigate("Register")}
>
<Text style={{ color: "#414959", fontSize: 13 }}>
New to SocialApp?{" "}
<Text style={{ fontWeight: "500", color: "#5B2B80" }}>
Sign Up
</Text>
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
titulo: {
color: "#5B2B80",
fontSize: 30,
fontWeight: "bold",
textAlign: "center",
marginTop: 150
},
errorMessage: {
height: 72,
alignItems: "center",
justifyContent: "center",
marginHorizontal: 30
},
error: {
color: "#5B2B80",
fontSize: 13,
fontWeight: "600",
textAlign: "center"
},
form: {
marginBottom: 48,
marginHorizontal: 60
},
inputTitle: {
color: "#8A8F9E",
fontSize: 10,
textTransform: "uppercase"
},
input: {
borderBottomColor: "#8A8F9E",
borderBottomWidth: StyleSheet.hairlineWidth,
height: 40,
fontSize: 15,
color: "#161F3D"
},
button: {
marginHorizontal: 60,
backgroundColor: "#5B2B80",
borderRadius: 4,
height: 52,
alignItems: "center",
justifyContent: "center"
}
});
export default Login;
App.js
import Login from "./components/Login";
import CreateAccount from "./components/CreateAccount";
import Chat from "./components/Chat";
import TelaTeste from "./components/TelaTeste";
// Import React Navigation
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
const AppNavigator = createStackNavigator({
Login: { screen: Login },
CreateAccount: { screen: CreateAccount },
Chat: { screen: Chat },
TelaTeste: TelaTeste
});
export default createAppContainer(AppNavigator);
Change, to use arrow function, this inside user() refers to a different thing
get user() {
return {
name: this.props.navigation.state.params.name,
email: this.props.navigation.state.params.email,
avatar: this.props.navigation.state.params.avatar,
id: firebaseSvc.uid,
_id: firebaseSvc.uid // need for gifted-chat
};
}
to
user = () => {
return {
name: this.props.navigation.state.params.name,
email: this.props.navigation.state.params.email,
avatar: this.props.navigation.state.params.avatar,
id: firebaseSvc.uid,
_id: firebaseSvc.uid // need for gifted-chat
};
}

Add subobject using setState method

I'm trying to add a new subobject to an existing object using the method this.setState in a expo application. The subobject are added after a click of a button, that update the fields that compons the subobject.
This is my code:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ImageBackground } from 'react-native';
import CenteredButton from '../components/CenteredButton';
import { Actions } from 'react-native-router-flux';
var t = require('tcomb-form-native');
var _ = require('lodash');
const Form = t.form.Form;
const stylesheet = _.cloneDeep(t.form.Form.stylesheet);
stylesheet.textbox.normal.borderColor = '#b3b3b5';
stylesheet.textbox.normal.fontFamily = 'RobotoThin';
stylesheet.textbox.normal.backgroundColor = '#fdfdfd';
stylesheet.textbox.normal.fontSize = 18;
stylesheet.textbox.normal.borderWidth = 0.6;
stylesheet.textbox.normal.borderRadius = 10;
stylesheet.textbox.error.fontFamily = 'RobotoThin';
stylesheet.textbox.error.backgroundColor = '#fdfdfd';
stylesheet.textbox.error.fontSize = 18;
stylesheet.textbox.error.borderWidth = 0.6;
stylesheet.textbox.error.borderRadius = 10;
const Email = t.refinement(t.String, email => {
const regex = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
return regex.test(email);
});
const EmailTo = t.struct({
emailPerson: Email,
emailInsurance: t.maybe(Email)
});
const options = {
auto: 'none',
stylesheet: stylesheet,
fields: {
emailPerson: {
placeholder: 'Email personale',
autoCapitalize: 'none',
autoCorrect: false,
},
emailInsurance: {
placeholder: 'Email Assicurazione',
autoCapitalize: 'none',
password: true,
}
}
}
export default class NessunProblema extends Component {
constructor(props) {
super(props);
this.state = {
emails: {
emailPerson: '',
emailInsurance: ''
},
ascertainment: { }
}
}
componentDidMount() {
this.setState({ ascertainment: this.props.ascertainment });
}
_onChange = (emails) => {
this.setState({ emails });
}
_handle = () => {
const value = this.refs.form.getValue();
if ( value ) {
this.setState(prev => ({
ascertainment: {
...prev.ascertainment,
emails: {
...prev.ascertainment.emails,
emailPerson: value.emailPerson,
emailInsurance: value.emailInsurance
}
}
}));
}
console.log(this.state.emails);
console.log(this.state.ascertainment);
}
render() {
return (
<View style={{flex: 1, backgroundColor: 'white' }}>
<ImageBackground source={require('../images/NoProblem.png')} style={styles.backgroundImage}>
<View style={{ flex: 2, alignItems: 'center', justifyContent: 'center', width: '100%', paddingHorizontal: 20, top: 10}}>
<Text style={styles.domanda}>
Text
</Text>
<Text style={styles.domanda2}>
Text
</Text>
</View>
<View style={{padding: 20}}>
<Form
ref='form'
options={options}
type={EmailTo}
value={this.state.emails}
onChange={this._onChange}
/>
</View>
<CenteredButton
next={ this._handle }
/>
</ImageBackground>
</View>
)
}
}
const styles = StyleSheet.create({
domanda: {
color: '#00b0ff',
textAlign: 'center',
fontSize: 44,
fontFamily: 'RobotoRegular',
alignItems: 'center',
justifyContent: 'center',
padding: 20
},
domanda2: {
color: 'black',
textAlign: 'center',
fontSize: 22,
fontFamily: 'RobotoRegular',
alignItems: 'center',
justifyContent: 'center',
padding: 20
},
testoRosso: {
color: '#f32a19',
fontFamily: 'RobotoRegular',
},
backgroundImage: {
flex: 1,
resizeMode: 'cover'
},
textInput: {
width: '100%',
paddingHorizontal: 15,
height: 40,
marginBottom: 20,
fontSize: 18,
borderWidth: 0.6,
borderColor: 'black',
borderRadius: 10,
color: 'black',
fontFamily: 'RobotoThin',
backgroundColor: 'white'
},
});
I noticed that, if I click TWO times the button AVANTI I obtein the correct result. But, WHY?
I follow this answer but doens't resolve the problem.
The problem is that setState() is not synchronous, the values are updated asynchronously
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.
_handle = () => {
const value = this.refs.form.getValue();
if ( value ) {
this.setState(prev => ({
ascertainment: {
...prev.ascertainment,
emails: {
...prev.ascertainment.emails,
emailPerson: value.emailPerson,
emailInsurance: value.emailInsurance
}
}
}));
}
console.log(this.state.emails); // will be the emails in the previous state, since setState has not been called yet by react
console.log(this.state.ascertainment); // if you click twice, you are still getting the `last` state, but since it is the same as the state you are setting the second time, you get the wrong idea that it is being set if you click twice!
}

JSON data in not coming on FlstList in react native

I know how to populate jSON data on FlatList and I have done that , but now here , I am populating data in between button and table data , In componentDidMount i am calling both function , first table create and then JSON call , Table data I am taking from QRCode scan from another screen and taking here .
import React, { Component } from 'react';
import { StyleSheet, View, ActivityIndicator, ScrollView } from 'react-native';
import { Table, Row, Rows } from 'react-native-table-component';
import {Button, Text, DatePicker, Item, Picker, Input,
Textarea,FlatList} from 'native-base';
export default class OpenApplianceIssue extends Component {
constructor(props) {
super(props);
this.state = {
// tableHead: ['Head', 'Head2', 'Head3', 'Head4'],
tableData: [], qrData: '', loading: false, selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
AbcSdata : null, loading : true,
}
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for(let i=0; i<len; i++)
{
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({tableData: tData } );
console.log(this.state.tableData);
this.setState({loading: true});
}
componentDidMount() {
this._loadInitialState().done();
// this.createViewGroup();
}
// componentDidMount() {
// this.createViewGroup();
// }
createViewGroup = async () => {
try {
const response = await fetch(
'http://Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit":"0",
"valuelimit":"10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
renderItem = ({ item }) => (
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={() => {
this.clickedItemText(item);
}}>
<Text style={styles.buttonText}>Id {item.inventory}</Text>
<Text>Inv {item.inventory}</Text>
<Text>Sensor {item.inventory}</Text>
</TouchableOpacity>
);
onClickListener = (viewId) => {
if(viewId == 'tag')
{
this.props.navigation.navigate('AddSensors');
}}
render() {
const state = this.state;
const AbcSdata = this.state;
if(this.state.loading == false) {
return ( <ActivityIndicator size='large' style={{height:80}} /> )
}
else {
return (
<ScrollView style={styles.container}>
<Button full rounded light style={{backgroundColor: 'blue', justifyContent: 'center', alignItems: 'center'}}
onPress={() => this.onClickListener('tag')}>
<Text style={{color: 'white'}}>Add Sensors</Text>
</Button>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
AbcSdata={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
)}
</View>
<View>
<Text
style={{alignSelf: 'center', fontWeight: 'bold', color: 'black'}} >
Inventory Details
</Text>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff', padding:10,paddingBottom: 10}}>
<Rows data={state.tableData} textStyle={styles.text}/>
</Table>
</View>
</ScrollView>
)
}
}
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
head: { height: 40, backgroundColor: '#f1f8ff' },
text: { margin: 6 }
});
try this code ..
import React, { Component } from 'react';
import { View, Text, TextInput,
FooterTab,Button,TouchableOpacity, ScrollView, StyleSheet,
ActivityIndicator ,Header,FlatList} from 'react-native';
import {Icon} from 'native-base';
import { Table, Row, Rows } from 'react-native-table-component';
import { createStackNavigator } from 'react-navigation';
import { SearchBar } from 'react-native-elements';
export default class OpenApplianceIssue extends Component {
constructor() {
super();
this.state = {
AbcSdata: null,
loading: true,
search: '',
tableData: [], qrData: '', selectedPriority: '',
selectedIssue: '', selectedReason: '', selectedTriedRestart: '',
selectedPowerLED: '', selectedBurning: '', selectedNoise: '',
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
}
_loadInitialState = async () => {
const { navigation } = this.props;
const qdata = navigation.getParam('data', 'NA').split(',');
var len = qdata.length;
const tData = [];
console.log(len);
for(let i=0; i<len; i++)
{
var data = qdata[i].split(':');
const entry = []
entry.push(`${data[0]}`);
entry.push(`${data[1]}`);
tData.push(entry);
}
this.setState({tableData: tData } );
console.log(this.state.tableData);
this.setState({loading: true});
}
componentDidMount() {
this._loadInitialState().done();
this.createViewGroup();
}
createViewGroup = async () => {
try {
const response = await fetch(
'http:Dsenze/userapi/sensor/viewsensor',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"password": 'admin',
"username": 'admin',
"startlimit":"0",
"valuelimit":"10",
}),
}
);
const responseJson = await response.json();
const { sensorData } = responseJson;
this.setState({
AbcSdata: sensorData,
loading: false,
});
} catch (e) {
console.error(e);
}
};
updateSearch = search => {
this.setState({ search });
};
keyExtractor = ({ id }) => id.toString();
keyExtractor = ({ inventory }) => inventory.toString();
renderItem = ({ item }) => (
<TouchableOpacity
style={styles.item}
activeOpacity={0.4}
onPress={() => {
this.clickedItemText(item);
}}>
<Text style={styles.buttonText}>Id {item.id}</Text>
<Text>Hospital Name {item.inventory}</Text>
<Text>User {item.inventory}</Text>
<Text>Date {item.inventory}</Text>
</TouchableOpacity>
);
onClickListener = (viewId) => {
if(viewId == 'tag')
{
this.props.navigation.navigate('AddSensors');
}}
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "86%",
backgroundColor: "#CED0CE",
}}
/>
);
};
render() {
const { loading, AbcSdata } = this.state;
const state = this.state;
return (
<ScrollView>
<View style={styles.container1}>
<TouchableOpacity full rounded light style={{backgroundColor: 'blue', justifyContent: 'center', alignItems: 'center'}}
onPress={() => this.onClickListener('tag')}>
<Text style={{color: 'white'}}>Add Sensors</Text>
</TouchableOpacity>
</View>
<View style={styles.container1}>
{this.state.loading ? (
<ActivityIndicator size="large" />
) :
(
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
/>
)}
</View>
<View>
<Text
style={{alignSelf: 'center', fontWeight: 'bold', color: 'black'}} >
Inventory Details
</Text>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff', padding:10,paddingBottom: 10}}>
<Rows data={state.tableData} textStyle={styles.text}/>
</Table>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create(
{
container1:
{
flex: 1,
alignItems: 'stretch',
fontFamily: "vincHand",
color: 'blue'
},
header_footer_style:{
width: '100%',
height: 44,
backgroundColor: '#4169E1',
alignItems: 'center',
justifyContent: 'center',
color:'#ffffff',
},
Progressbar:{
justifyContent: 'center',
alignItems: 'center',
color: 'blue',
},
ListContainer :{
borderColor: '#48BBEC',
backgroundColor: '#000000',
color:'red',
alignSelf: 'stretch' ,
},
container2:
{
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
paddingHorizontal: 15
},
inputBox:{
width:300,
borderColor: '#48BBEC',
backgroundColor: '#F8F8FF',
borderRadius:25,
paddingHorizontal:16,
fontSize:16,
color:'#000000',
marginVertical:10,
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
textStyle:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
item:
{
padding: 15
},
text:
{
fontSize: 18
},
button:{
width:300,
backgroundColor:'#4169E1',
borderRadius:25,
marginVertical:10,
paddingVertical:16
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'red',
textAlign:'center'
},
separator:
{
height: 2,
backgroundColor: 'rgba(0,0,0,0.5)'
},
container: { flex: 1, padding: 16, paddingTop: 30, backgroundColor: '#fff' },
head: { height: 40, backgroundColor: '#f1f8ff' },
text: { margin: 6 }
});
In your FlatList component you are setting AbcSdata={AbcSdata}, while you should be setting the data prop:
<FlatList
data={AbcSdata}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
It could be because _loadInitialState in your componentDidMount is an async call and table is getting rendered initially with no data. You could try passing in some prop to refresh once you have data. Also, in the code you put here, all calls to createViewGroup() are commented out but the definition is still there. Not a big problem but still very confusing for someone looking into your code.

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

My navigation suddenly broke down. So there are 3 screens/components, I am using react-navigation to navigate between them. First screen is to enter mobile phone number and password, it is sent to api, and some data is saved into state and passed to second screen, where i am enter code from sms and send another request to api, if response.status == 200, it goes to third screen. Navigation from 1st screen to 2nd works, but from 2nd to third is not. Error occurs when i am going to third screen.
FirstPage.js
export default class FirstPage extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
password: '',
password2: ''
}
}
state = {
uuid: null
}
getCode(text, psw) {
fetch('url', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"telephone": text, "password": psw})
})
.then(response => response.json())
.then(response => {
let uuid = response['data']['id'];
this.setState({uuid});
this
.props
.navigation
.navigate('SecondPage', {uuid});
})
};
render() {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center"
}}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View
style={{
width: 200,
height: 60,
borderColor: 'gray',
borderWidth: 1,
justifyContent: "center",
alignItems: "center"
}}>
<View>
<Text>phone number
</Text>
</View>
<View>
<TextInput
keyboardType='phone-pad'
onChangeText={(text) => this.setState({text})}
value={this.state.text}
placeholder={"phone number"}/>
</View>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View
style={{
width: 200,
height: 60,
marginTop: 25,
borderColor: 'gray',
borderWidth: 1,
justifyContent: "center",
alignItems: "center"
}}>
<View>
<Text>password</Text>
</View>
<View>
<TextInput
keyboardType='phone-pad'
secureTextEntry
onChangeText={(password) => this.setState({password})}
value={this.state.password}
placeholder={"password"}/>
</View>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View
style={{
width: 200,
height: 60,
marginTop: 25,
borderColor: 'gray',
borderWidth: 1,
justifyContent: "center",
alignItems: "center"
}}>
<Text>password2</Text>
<TextInput
keyboardType='phone-pad'
secureTextEntry
onChangeText={(password2) => this.setState({password2})}
value={this.state.password2}
placeholder={"password2"}/>
</View>
</TouchableWithoutFeedback>
<Button
title="getcode"
onPress={() => this.getCode(this.state.text, this.state.password)}/>
</View>
);
}
}
SecondPage.js
export default class SecondPage extends React.Component {
input = React.createRef();
constructor(props) {
super(props);
this.state = {
value: "",
focused: false,
uuid: this.props.navigation.state.params.uuid,
};
}
state = {
codeConf: '',
}
sendCode(uid, code) {
const body = new FormData
body.append("authentication", uid)
body.append("code", code)
fetch('url', {
method: 'POST',
body,
headers: {
Token: "2f30743e-014d-4f0f-8707-73ae550d8f14"
}
}).then(function (response) {
console.log(uid + "code is " + code)
console.log(response);
if (response.ok) {
this.props.navigation.navigate('ThirdPage');
} else {
console.log(response.status)
}
})
.catch((error) => {
console.error(error);
});
}
render() {
return (
<View
style={{
flex: 1,
backgroundColor: '#FDD7E4',
alignSelf: 'stretch',
textAlign: 'center',
borderWidth: 1,
justifyContent: "center",
alignItems: "center"
}}>
<CodeInput
ref="codeInputRef2"
secureTextEntry
codeLength={6}
keyboardType='phone-pad'
activeColor='rgba(0, 0, 0, 1)'
inactiveColor='rgba(0, 0, 0 , 0.1)'
autoFocus={true}
ignoreCase={true}
inputPosition='center'
size={50}
onFulfill={(code) => {
this.setState({codeConf: code})
}}/>
<Button
title="send code"
onPress={this.sendCode(this.state.uuid, this.state.codeConf)} />
</View>
)
}
}
ThirdPage.js
export default class ThirdPage extends React.Component {
render() {
return (
<View style={styles}>
<Text>
Hi there
</Text>
</View>
)
}
}
And finally App.js
class App extends React.Component {
render() {
return (<AppStackNavigator />)
}
}
const AppStackNavigator = createStackNavigator({
FirstPage: {
screen: FirstPage
},
SecondPage: {
screen: SecondPage
},
ThirdPage: {
screen: ThirdPage
}
}, {initialRouteName: 'FirstPage'})
export default createAppContainer(AppStackNavigator);
I don't really why it happens, because react-navigation says that all then screens from App.js is sent to every screen as this.props.navigation, so I can access them from anywhere.
The issue is because you have lost scope by not binding your functions, this means that you are no longer accessing the correct value of this. You can fix this issue by using arrow functions.
Rewrite your sendCode function in the following way, noticing the use of arrow functions
sendCode = (uid, code) => { // <- arrow function
const body = new FormData();
body.append('authentication', uid);
body.append('code', code);
fetch('url', {
method: 'POST',
body,
headers: {
Token: '2f30743e-014d-4f0f-8707-73ae550d8f14'
}
}).then(response => { // <- arrow function
console.log(uid + 'code is ' + code);
console.log(response);
if (response.ok) {
this.props.navigation.navigate('ThirdPage');
} else {
console.log(response.status);
}
}).catch((error) => {
console.error(error);
});
}
And finally update the code in your button to be.
<Button
title="send code"
onPress={() => this.sendCode(this.state.uuid, this.state.codeConf)} />
you need to bind and pass function definition to onPress prop of Button component in SecondPage.js.
<Button
title="send code"
onPress={()=>this.sendCode(this.state.uuid,this.state.codeConf)} />

Categories