Login React Native MySQL - javascript

We been having an issue with our login code. We keep receiving an SyntaxError: JSON Parse Error:
We narrowed down the response error happens during one of the .then(response) lines or in the php code. I'm not sure what I'm doing wrong here. Any help?!
loginScreen.js
login = () =>{
const { UserEmail } = this.state ;
const { UserPassword } = this.state ;
fetch('http://localhost:65535/login.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_email: UserEmail,
user_pass: UserPassword
})
//Error within line 59-61 or php
})
.then((response) => response.json())
.then((responseJson) => {
// If server response message same as Data Matched
if(responseJson === 'Data Matched'){
alert("Correct");
} else{
alert("Incorrect");
}
}).catch((error) => {
console.error(error);
});
}
render() {
return (
<View style={styles.container}>
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}>
<View style={styles.welcomeContainer}>
<Image
source={
__DEV__
? require('../assets/images/HootLogo.png')
: require('../assets/images/robot-prod.png')
}
style={styles.welcomeImage}
/>
</View>
login.php Seems like everything is laid out correctly and works functionaly. I tried changing ' to ` and everything.
<?php
// Importing DBConfig.php file.
include 'DBConfig.php';
// Creating connection.
$con = mysqli_connect($HostName,$HostUser,$HostPass,$DatabaseName);
// Getting the received JSON into $json variable.
$json = file_get_contents('php://input');
// decoding the received JSON and store into $obj variable.
$obj = json_decode($json,true);
// Populate User email from JSON $obj array and store into $email.
$user_email = $obj['user_email'];
// Populate Password from JSON $obj array and store into $password.
$user_pass = $obj['user_pass'];
//Applying User Login query with email and password match.
$Sql_Query = "select * from wp_users where user_email = '$user_email' and user_pass = '$user_pass' ";
// Executing SQL Query.
$check = mysqli_fetch_array(mysqli_query($con,$Sql_Query));
if(isset($check)){
$SuccessLoginMsg = 'Data Matched';
// Converting the message into JSON format.
$SuccessLoginJson = json_encode($SuccessLoginMsg);
// Echo the message.
echo $SuccessLoginJson ;
} else{
// If the record inserted successfully then show the message.
$InvalidMSG = 'Invalid Username or Password Please Try Again' ;
// Converting the message into JSON format.
$InvalidMSGJSon = json_encode($InvalidMSG);
// Echo the message.
echo $InvalidMSGJSon ;
}
mysqli_close($con);
?>
Full JS Code
import React, { Component } from 'react';
import {
AppRegistry,
Image,
Input,
Platform,
Button,
Keyboard,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
TextInput,
View,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
export default class login extends Component {
static navigationOptions= ({navigation}) =>({
title: 'Login',
headerRight:
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={{backgroundColor: '#f7f7f7'}}>
</TouchableOpacity>
});
constructor(props){
super(props)
this.state={
userEmail:'',
userPassword:''
}
}
login = () =>{
const { UserEmail } = this.state ;
const { UserPassword } = this.state ;
fetch('http://192.168.0.13:65535/login.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_email: UserEmail,
user_pass: UserPassword
})
}).then((response) => response.json())
.then((responseJson) => {
// If server response message same as Data Matched
if(responseJson === 'Data Matched')
{
//Then open Profile activity and send user email to Home After Login.
alert(responseJson);
}
else{
alert(responseJson);
}
}).catch((error) => {
console.error(error);
});
}
render() {
return (
<View style={styles.container}>
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}>
<View style={styles.welcomeContainer}>
<Image
source={
__DEV__
? require('../assets/images/HootLogo.png')
: require('../assets/images/robot-prod.png')
}
style={styles.welcomeImage}
/>
</View>
<View style={styles.errorContainer}>
<Text style={{padding:10,margin:10,color:'red'}}>{this.state.email}</Text>
</View>
<View style={styles.container}>
<Text style={styles.headerText}>Username</Text>
</View>
<TextInput
placeholder="Enter Email"
style={styles.input}
onChangeText={userEmail => this.setState({userEmail})}
/>
<View style={styles.container}>
<Text style={styles.headerText}>Password</Text>
</View>
<TextInput
placeholder="Enter Password"
style={styles.input}
secureTextEntry
onChangeText={userPassword => this.setState({userPassword})}
/>
<TouchableOpacity style={styles.buttonContainer}
onPress={this.login}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<View style={styles.loginContainer}>
<Text style={styles.loginText}>Don't Have an Account?</Text>
<TouchableOpacity style={styles.emailButtonContainer}
onPress={() => this.props.navigation.navigate('Links')}>
<Text style={styles.loginButtonText}>Register</Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
contentContainer: {
paddingTop: 10,
},
welcomeContainer: {
alignItems: 'center',
},
welcomeImage: {
width: 250,
height: 230,
resizeMode: 'contain',
marginLeft: -10,
},
errorContainer: {
flex: 1,
backgroundColor: '#fff',
marginTop: -55,
alignSelf: 'center',
},
headerText: {
fontSize: 20,
color: 'rgba(96,100,109, 1)',
lineHeight: 24,
marginLeft: 50,
marginBottom: 10,
},
input: {
height: 40,
borderBottomColor: 'rgba(0,0,0,0.4)',
borderBottomWidth: 3,
padding: 10,
marginBottom: 10,
marginHorizontal: 50,
},
buttonContainer: {
backgroundColor: '#78AA3A',
padding: 15,
marginTop: 10,
marginHorizontal: 50,
borderColor: '#fff',
borderRadius:10,
borderWidth: 1,
},
buttonText: {
textAlign: 'center',
color: '#FFFFFF',
},
loginContainer: {
textAlign: 'center',
marginTop: 10,
flexDirection: 'row',
},
loginText: {
marginLeft: 80,
marginBottom: 20,
color: 'rgba(0,0,0,0.4)',
fontSize: 14,
lineHeight: 19,
},
loginButtonText: {
fontSize: 14,
color: '#78AA3A',
paddingLeft: 5
},
});
AppRegistry.registerComponent('login', () => login);

From what I can see the issue is that your PHP server does not return valid json. It returns a string, even though you do json_encode the string, the string will either be "Data Matched" or "Invalid Username or Password Please Try Again". However, when you make the fetch request and do
.then((response) => response.json())
.then((responseJson) => {
It attempts to parse the string "Data Matched" when you do response.json()).then((responseJson) the .json() part is trying to parse the string that is invalid JSON. So you can resolve this in two ways actually send valid json back from the php server build an object like this { "success" : true, message :"Data Matched"} or simply remove the .json() chain, so then javascript will return a string and not try to parse it as JSON. So without the .json() it will be
...
.then((response) => {
// If server response message same as Data Matched
if(response === 'Data Matched')
{
alert(response);
} else {
alert(response);
}
...
Simply try removing .then((response) => response.json() part on line 58 first, and skipping directly to the next chained then clause

i think you need to try change the code
fetch('http://localhost:65535/login.php'....
to your ip, check your local ip using ipconfig
and change the code like this
fetch('http://192.168.1.1/login.php'....
sample ip

Related

How to pass parameter from AsyncStorage to function React Native

I have a login page. There, the user enters data and submits to the API. The API gives an answer that there is such a user and gives him an id from the database. I write this id in storage.
Next, the user is taken to the home page.
There is a component that is responsible for getting the username (and indeed all other data)
the essence of the component:
1 The parameter receives an id and forms it into a json request.
2 The parameter sends this request to the API and receives the user's data in the response (if the id matches)
3) return which draws the interface and gives the user data from the API response
Problem:
When changing an account (or re-logging in), it gives a json request error (in fact, the API does not accept an empty request, so it rejects it)
The point of getting an ID is 100%. When the application is updated again, the id turns out to be generated in json and after that I already get data about the user.
How to fix it? In fact, it must first receive the id, and only then the id is sent and the data is received, however, at the first entry into the application, he does not want to receive the ID immediately, but only after a reboot (ctlr + s in VS code)
//LOGIN.js
import React, { Component } from 'react';
import { View, Pressable, Text, TextInput, TouchableOpacity } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
import styles from './style';
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email : '',
password : '',
check_textInputChange : false,
secureTextEntry : true,
id : '',
};
}
componentDidMount(){
this._loadInitialState().done();
}
//Сheck that the user with id does not throw out on the authorization screen when exiting the application:
_loadInitialState = async () => {
var id = await AsyncStorage.getItem('id');
if (id !== null) {
this.props.navigation.navigate("HomeScreen")
this.id = id
}
}
InsertRecord () {
var Email = this.state.email;
var Password = this.state.password;
if ((Email.length==0) || (Password.length==0)){
alert("Missing a required field!");
}else{
var APIURL = "http://10.0.2.2:8080/SignIn/login.php";
var headers = {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
};
var Data ={
Email: Email,
Password: Password
};
fetch(APIURL,{
method: 'POST',
headers: headers,
body: JSON.stringify(Data)
})
.then((Response)=>Response.json())
.then((Response)=>{
alert(Response[0].Message)
if (Response[0].Message == "Success") {
console.log(Response[0].Message)
// eslint-disable-next-line react/prop-types
AsyncStorage.setItem('id',Response[0].Id);
this.props.navigation.navigate("HomeScreen");
console.log(Response[0].Id);
}
console.log(Data);
})
.catch((error)=>{
console.error("ERROR FOUND" + error);
})
}
}
updateSecureTextEntry(){
this.setState({
...this.state,
secureTextEntry: !this.state.secureTextEntry
});
}
render() {
return (
<View style={styles.viewStyle}>
<View style={styles.action}>
<TextInput
placeholder="Enter Email"
placeholderTextColor="#ff0000"
style={styles.textInput}
onChangeText={email=>this.setState({email})}
/>
</View>
<View style={styles.action}>
<TextInput
placeholder="Enter Pass"
placeholderTextColor="#ff0000"
style={styles.textInput}
secureTextEntry={this.state.secureTextEntry ? true : false}
onChangeText={password=>this.setState({password})}
/>
<TouchableOpacity
onPress={this.updateSecureTextEntry.bind(this)}>
</TouchableOpacity>
</View>
{/* Button */}
<View style={styles.loginButtonSection}>
<Pressable
style={styles.loginButton}
onPress={()=>{
this.InsertRecord()
}}
>
<Text style={styles.text}>Войти</Text>
</Pressable>
</View>
</View>
);
}
}
//INFOSTATUS.js
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, TouchableOpacity, SafeAreaView, FlatList, StyleSheet, Button, View, Text } from 'react-native';
import { useNavigation } from '#react-navigation/native'
import AsyncStorage from '#react-native-async-storage/async-storage';
function InfoStatus() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [idUser, setIdUser] = useState();
//check ID
const idcheck = async () => {
try {
const get = await AsyncStorage.getItem('id')
setIdUser (get)
} catch(e) {
// read error
}
}
//Sending data to api and getting user data
const getNotifications = async () => {
const send = {
id:idUser
}
try {
const response = await fetch('http://10.0.2.2:8080/InfoStatus/InfoStatus.php', {
method: 'POST',
body: JSON.stringify(send),
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
setData(data);
console.log(data);
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
useEffect(() => {
idcheck();
getNotifications();
}, []);
//Initialization of received data
const Item = ({ name, middlename,status,number,city }) => (
<View style={StyleInfo.container}>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Dear, </Text>
<Text style={StyleInfo.TextStyleData} key ={name}> {name} {middlename} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Number: </Text>
<Text style={StyleInfo.TextStyleData}key ={number}> № {number} </Text>
<TouchableOpacity
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.ButtonAdress}>Find out the address</Text>
</TouchableOpacity>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> Status: </Text>
<Text style={StyleInfo.TextStyleData} key ={status}> {status} </Text>
</View>
<View style={StyleInfo.container2}>
<Text style={StyleInfo.TextStyle}> City: </Text>
<Text style={StyleInfo.TextStyleData} key ={city}> {city} </Text>
</View>
<TouchableOpacity
style={StyleInfo.Button}
onPress={() =>
navigation.navigate('InfoParser')
}
>
<Text style={StyleInfo.TextButton}>Get contacts of friends</Text>
</TouchableOpacity>
</View>
);
const renderItem = ({ item }) => (
<Item name={item.name} middlename={item.middlename} status={item.status} yik={item.yik} elections={item.elections} />
);
return (
<SafeAreaView>
{isLoading ? <ActivityIndicator size="large" color="#00ff00"/> : (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
)}
</SafeAreaView>
);
}
const StyleInfo = StyleSheet.create({
container:{
width: 390,
height: 190,
borderWidth: 1,
borderRadius: 2,
marginLeft: 10,
marginBottom: 10,
backgroundColor: '#E9E9E9',
},
container2:{
flexDirection: "row",
},
TextStyle: {
fontFamily: 'Raleway',
fontStyle: 'normal',
fontWeight: 'normal',
fontSize: 18,
marginTop: 5,
marginLeft: 5,
bottom: 10,
top: 10
},
TextStyleData: {
fontSize: 18,
marginTop: 5,
top: 10,
fontWeight: 'bold',
},
ButtonAdress: {
fontSize: 18,
marginTop: 5,
marginLeft: 20,
top: 10,
color: "#ff0000",
},
Button: {
width: 310,
height: 40,
marginTop: 10,
marginLeft: 5,
bottom: 10,
borderWidth: 1,
borderRadius: 2,
top: 10,
alignSelf: 'center',
backgroundColor: "#ff0000",
},
TextButton: {
marginTop: 5,
fontSize: 16,
alignSelf: 'center',
fontWeight: 'bold',
color: 'white',
}
}
)
export {InfoStatus}
PS:
I also caught one thing that when I try to get an id via async / await, then most likely the point is that it does not have time to get the value before rendering. I have run out of ideas, I would like to receive more other suggestions
PSS:
I also know that in fact, even if I passed the value through the navigator, I would pass it to the homescreen. Although my InfoStatus is embedded in the Homescreen and I need to somehow pass this parameter there.
Although in general the question interests me a lot, because I will need this parameter everywhere. Therefore, finding one universal solution would be cool.
I am not 100% sure I understand the question so here a few hints I would give you.
You can pass parameters when navigating like this:
navigation.navigate('somescreen', {
param: 86,
otherParam: 'myBestFriendTheParam',
})
On the next screen you have to then read it from the route.params.
You could use redux to have your user data at hand while the app is open and user logged in? That would give you the data where ever you want basically.
If async/wait does not work why don't you use then-chains like in the rest of your code?

Can't Upload an image from Expo& React Native and POST to a flask backend

I am trying to upload an image with react native/ expo, and send it to a Python Flask backend Server. However, in my Flask server, I am having this error: werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
Here is the code to upload the image (which works fine):
import React from "react";
import {
StyleSheet,
Text,
View,
Image,
Button,
Alert,
TouchableOpacity,
} from "react-native";
import * as ImagePicker from "expo-image-picker";
import * as Permissions from "expo-permissions";
import { editProfilePicture } from "../functions/network_authentication";
import { onPressHandler } from "../functions/utils";
export default class EditPicture extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
image: null,
};
}
handleChange(event) {
this.setState({
image: event,
});
console.log("handle change ok");
console.log(this);
}
askForPermission = async () => {
const permissionResult = await Permissions.askAsync(Permissions.CAMERA);
if (permissionResult.status !== "granted") {
Alert.alert("no permissions to access camera!", [{ text: "ok" }]);
return false;
}
return true;
};
takeImage = async () => {
// make sure that we have the permission
const hasPermission = await this.askForPermission();
if (!hasPermission) {
console.log("no permission");
return;
} else {
console.log("permission");
// launch the camera with the following settings
let image = await ImagePicker.launchCameraAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [3, 3],
quality: 1,
//base64: true,
});
console.log("image got");
// make sure a image was taken:
if (!image.cancelled) {
console.log("image not canceled");
console.log(image);
this.handleChange(image);
}
}
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={{ justifyContent: "center", alignItems: "center" }}
onPress={this.takeImage}
>
<Text
style={{ alignSelf: "center", fontSize: 20, fontWeight: "bold" }}
>
Upload
</Text>
</TouchableOpacity>
{this.state.image != null ? (
<View
style={{
justifyContent: "center",
alignItems: "center",
alignSelf: "center",
marginTop: "3em",
height: "30%",
width: "15%",
borderWidth: 4,
borderColor: "black",
}}
>
<Image
source={this.state.image}
style={{width: "100%", height: "100%", alignSelf: "center"}}
/>
</View>
) : null}
<TouchableOpacity
style={{
width: "80%",
height: "10%",
alignSelf: "center",
borderRadius: 8,
borderWidth: 3,
borderColor: "#000000",
bottom: 20,
position: "absolute",
alignContent: "center",
justifyContent: "center",
}}
onPress={() => {
let result = editProfilePicture(this.state.image);
result.then((res) => {
if (res) {
onPressHandler(
this.state.navigation,
"SuccessEdit",
);
}
});
}}
>
<Text style={{ alignSelf: "center", fontWeight: "bold" }}>
Send the picture !
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
flexDirection: "column",
},
});
As you can see, when we press on send the picture, we are running the function editProfilePicture:
export const editProfilePicture = async (uploaded_image) => {
let form_data = new FormData();
form_data.append("input_image", uploaded_image, "photo.jpg");
try {
let response = await fetch(
"127.0.0.1:5000/change_profile_picture",
{
body: form_data,
method: "put",
credentials: "include",
}
);
if (response.ok) {
let json = await response.json();
return true;
} else {
console.log("Not OK");
return false;
}
} catch (error) {
console.error(error);
return false;
}
};
The request is sent to the Flask server, but in my endpoint, I am having the 400 error at this line:
#auth.route("/change_profile_picture", methods=["PUT"])
#jwt_refresh_token_required
def change_profile_picture():
"""
To do when the other endpoints work
"""
input_image = request.files["input_image"] # HERE !
Conclusion: I think the problem comes from the way I want to send the picture. How should I do it? I don't know anything about Blob, Canvas, etc. so some lines of code would be welcome !
In formdata apoend file in option give name src and type

Using Mutation hook to update data in Graphql server

Actually I am new to React Native. In my recent project, I have faced an issue while using useMutation hook for updating the data in my server. I have attached the file in which I am using it.
For your reference, I have attached the screenshot of the playground.
Note:- I am not getting an error and the values are not updated in the server. If I click on the button. It is not required to refetch it and display the info using a query, just an update would be enough.
Mutation structure:
.
graphql request sent:
import React, { Component,useState } from 'react';
import { View, Text, StyleSheet, Dimensions,ScrollView,AsyncStorage,TouchableHighlight,Alert,KeyboardAvoidingView} from 'react-native';
import TopHeader from '../../Header/TopHeader';
import { gql } from 'apollo-boost';
import Input from '../../SignIn/Input';
import { ScreenLoader } from '../../Loader';
import { useMutation } from '#apollo/react-hooks';
export const UPDATE_USER_DETAILS = gql`
mutation UpdateUser($input: AccountInput!){
accountUpdate(input: $input){
accountErrors{
message
}
user{
id
email
firstName
lastName
}
}
}
`;
const getToken = async () => {
const token = await AsyncStorage.getItem('token');
console.log("Token = "+token);
return token;
}
function UpdateUserComponent({ firstname,lastname }) {
const [newfirstName, setNewfirstName] = useState(firstname);
const [newlastName, setNewlastName] = useState(lastname);
var token = getToken();
console.log("Inside Update User Component");
const [updateUser,{loading,data,error}] = useMutation(UPDATE_USER_DETAILS,{
headers: {
Authorization: token ? `Bearer ${token}` : ''}
})
if (loading) return <ScreenLoader/>
if (error){
console.log(error);
return <Text>Error...</Text>
}
console.log(data);
return (
<KeyboardAvoidingView style={styles.container} behavior='padding' enabled>
<ScrollView>
<View style={{ paddingTop: 36 }}>
<Input type="text" value={newfirstName} onChange={e => setNewfirstName(e.target.value)} />
<View style={{ paddingTop: 10 }}>
<Input type="text" value={newlastName} onChange={e => setNewlastName(e.target.value)}/>
</View>
<TouchableHighlight underlayColor='#fff' onPress={() => updateUser({ variables: { "input": {"firstName": newfirstName,"lastName": newlastName }} })} >
<View style={{ paddingTop: 50 }}>
<View style={styles.buttonLayout}>
<Text style={styles.buttonText}>Save Changes</Text>
</View>
</View>
</TouchableHighlight>
</View>
</ScrollView>
</KeyboardAvoidingView>
)
}
const width = Dimensions.get('window').width;
class AccountSettings extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<TopHeader text='Account Settings'/>
<UpdateUserComponent/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
paddingTop: 20,
},
buttonLayout: {
backgroundColor: '#C5C5C5',
width: width * 85 / 100,
height: 45,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 20,
},
buttonText: {
color: '#919191',
fontSize: 14
},
})
export default AccountSettings;
Update:
There is some error in getting the values from Form Input Elements. If I assign values directly it is updating. For Example:- if I use this statement on button press, the data is updated on the server.
onPress={() => UpdateUser({ variables: { "input": {"firstName": "Prabhu","lastName": "Visu" }} }) }
Please help me in fixing this issue, making it work dynamically. Thanks .!
Replace This:
*onChange={e => setNewfirstName(e.target.value)}*
With This:
*onChangeText={text => setNewfirstName(text)}*
It will be working.!

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)} />

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

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.

Categories