How to pass value to constructor this.setstate in react native - reactjs

Currently I want to setState of userId inside the constructor. The thing I want is to get the firebase.auth.currentUser.uid stored to the userId when Login is successful or handleLogin called.
I have a poor knowledge in Programming. So please ignore the other errors in the programs.
My code:
import React from 'react';
import { StyleSheet,
Text,
View,
TouchableOpacity,
AsyncStorage,
} from 'react-native';
import {RkTextInput, RkButton } from 'react-native-ui-kitten';
import {Actions} from 'react-native-router-flux';
import { createSwitchNavigator, createAppContainer } from 'react-navigation';
import Profile from "../Profile/Profile";
import SignUp from '../SignUp/SignUp';
import * as firebase from 'firebase';
export default class Login extends React.Component {
constructor(props){
super(props)
this.state=({
email:'savadks1919#gmail.com',
password:'123123',
userId:'',
errorMessage: null
})
}
componentDidMount() {
this._loadInitialState().done();
}
_loadInitialState = async () => {
let value= await AsyncStorage.getItem(this.state.userId)
}
signup() {
Actions.signup()
}
Home() {
Actions.home()
}
handleLogin = (email, password, userId) => {
firebase.auth().signInWithEmailAndPassword(email, password).then(
this.setstate ({
userId: firebase.auth().currentUser.uid
}),
alert(this.state.userId)
).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
});
}
render() {
return (
<View style={styles.container}>
<Text style={styles.titleText}>Taams</Text>
<Text style={styles.edition}>Developer's Edition</Text>
<Text style={styles.titleText}>Login.js</Text>
<Text>Alpha 0.0.0.1</Text>
{/*-----UserName Input-------*/}
<RkTextInput
rkType= 'rounded'
labelStyle= {{color: 'black', fontWeight: 'bold'}}
placeholder='UserName'
//--------------value Handler----------------//
onChangeText={(email) => this.setState({email})}
//---------------------------------//
selectionColor="#000000"
keyboardType="email-address"
onSubmitEditing={() => { this.password.focusInput(); }}
inputStyle={{
color: 'black',
fontWeight: 'bold',
}}/>
{/*-----Password-------*/}
<RkTextInput
secureTextEntry={true}
rkType= 'rounded'
placeholder='Password'
//--------------value Handler----------------//
onChangeText={(password) => this.setState({password})}
//---------------------------------//
ref={(input) => { this.password = input; }}
inputStyle={{
color: 'black',
fontWeight: 'bold',
}}/>
<RkButton onPress = {()=>this.handleLogin(this.state.email,this.state.password)}>
<Text style={styles.LoginButtonText}>Login</Text>
</RkButton>
<View style={styles.signupTextCont}>
<Text style={styles.signupText}>Don't have an account yet?</Text>
<TouchableOpacity onPress={this.signup}><Text style={styles.signinButton}>SignUp</Text></TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
signupTextCont:{
flexGrow: 0,
alignItems:'center',
justifyContent:'flex-end',
marginVertical:15
},
signupText:{
color:'rgba(64,64,64,0.6)',
fontSize:16
},
signinButton:{
color:'#000000',
fontSize:16,
fontWeight:'500'
},
titleText: {
fontSize: 20,
fontWeight: 'bold',
},
edition: {
fontSize: 15,
//fontWeight: 'bold',
},
TextInput: {
width: 300,
height:50,
borderColor: 'grey',
borderWidth: 1,
},
LoginButtonText: {
fontSize: 20,
fontWeight: 'bold',
color: 'white',
//alignItems: 'center'
},
});

If you are coming from different screen with navigation on login screen then you need to pass userId in Params of react-navigation like this
this.props.navigation.navigate('Login', params)
and get these params in your constructor like this to get the userId
this.props.navigation.getParams('params')
if you are on the login screen and calling your auth function for authentication of user and also you need this Data in your component then you need to setState on the response of your auth function
setState({userData: res})
Or you can do initialisation inside constructor
this.state={ userId: firebase.auth.currentUser.uid }

Related

React Native AsyncStorage : blank page error

I'm trying to save my data locally with AsyncStorage but there seems to be an issue when I use getData
const storeData = async (value: string) => {
//storing data to local storage of the device
try {
await AsyncStorage.setItem("#storage_Key", value);
} catch (e) {}
};
const getData = async () => {
try {
const value = await AsyncStorage.getItem("#storage_Key");
if (value !== null) {
// value previously stored
}
} catch (e) {}
};
...
<View>
<TextInput
editable
value={value}
/>
{storeData(value)}
{getData()}
</View>
I thought I would have my value back but I got a blank page. Any idea of how to use AsyncStorage ? I used https://react-native-async-storage.github.io/async-storage/docs/usage/ .
Instead of calling storeData function in the return, you should bind your async storage function to the textinput component. Below is an example code on how to use it.
// AsyncStorage in React Native to Store Data in Session
// https://aboutreact.com/react-native-asyncstorage/
// import React in our code
import React, { useState } from 'react';
// import all the components we are going to use
import {
SafeAreaView,
StyleSheet,
View,
TextInput,
Text,
TouchableOpacity,
} from 'react-native';
// import AsyncStorage
import AsyncStorage from '#react-native-community/async-storage';
const App = () => {
// To get the value from the TextInput
const [textInputValue, setTextInputValue] = useState('');
// To set the value on Text
const [getValue, setGetValue] = useState('');
const saveValueFunction = () => {
//function to save the value in AsyncStorage
if (textInputValue) {
//To check the input not empty
AsyncStorage.setItem('any_key_here', textInputValue);
//Setting a data to a AsyncStorage with respect to a key
setTextInputValue('');
//Resetting the TextInput
alert('Data Saved');
//alert to confirm
} else {
alert('Please fill data');
//alert for the empty InputText
}
};
const getValueFunction = () => {
//function to get the value from AsyncStorage
AsyncStorage.getItem('any_key_here').then(
(value) =>
//AsyncStorage returns a promise so adding a callback to get the value
setGetValue(value)
//Setting the value in Text
);
};
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<Text style={styles.titleText}>
AsyncStorage in React Native to Store Data in Session
</Text>
<TextInput
placeholder="Enter Some Text here"
value={textInputValue}
onChangeText={(data) => setTextInputValue(data)}
underlineColorAndroid="transparent"
style={styles.textInputStyle}
/>
<TouchableOpacity
onPress={saveValueFunction}
style={styles.buttonStyle}>
<Text style={styles.buttonTextStyle}> SAVE VALUE </Text>
</TouchableOpacity>
<TouchableOpacity onPress={getValueFunction} style={styles.buttonStyle}>
<Text style={styles.buttonTextStyle}> GET VALUE </Text>
</TouchableOpacity>
<Text style={styles.textStyle}> {getValue} </Text>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 10,
backgroundColor: 'white',
},
titleText: {
fontSize: 22,
fontWeight: 'bold',
textAlign: 'center',
paddingVertical: 20,
},
textStyle: {
padding: 10,
textAlign: 'center',
},
buttonStyle: {
fontSize: 16,
color: 'white',
backgroundColor: 'green',
padding: 5,
marginTop: 32,
minWidth: 250,
},
buttonTextStyle: {
padding: 5,
color: 'white',
textAlign: 'center',
},
textInputStyle: {
textAlign: 'center',
height: 40,
width: '100%',
borderWidth: 1,
borderColor: 'green',
},
});
export default App;

Why I am getting an error 400 response instead of my expected response when a duplicate user exists?

I am creating an Application using React Native and Node.js at the backend. I am using Axios to call the API services. The API will show a response if a user is created successfully. Fortunately it shows. However if an user already exists, then it is still supposed to return a message by saying "User already exists". This however works with postman but unfortunately when I try from my react native front-end, I am getting an Error 400. Basically, I want to show my user that particular message where the API returns that user already exists. Here is my code:
import React, { Component } from "react";
import { render } from "react-dom";
import { ImageBackground, SafeAreaView, StyleSheet, View, Image, Text, Button, TouchableWithoutFeedback, TouchableOpacity, TextInput } from "react-native";
import axios from "axios";
class Welcome extends Component {
constructor() {
super();
this.state = {
username : "",
email : "",
password: "",
}
}
submit = () => {
console.log(this.state.email);
console.log(this.state.username);
console.log(this.state.password);
//Here comes the magic
axios
.post(`http://localhost:8080/api/auth/signup`, {
username: this.state.username,
email: this.state.email,
password: this.state.password,
})
.then((response) => {
console.log(response.data);
});
}
render() {
const test = () => {
console.log("Test Completed");
}
const buttonFeedback = (data) => {
if(data === 1) {
console.log("Login Button Detected!");
}
if(data === 2) {
console.log("Registration Button Detected!");
}
}
return (
<>
<ImageBackground style={styles.background}
source={require("../assets/background.png")}>
<View style={styles.logoContainer}>
<Image style={styles.logo} source={require("../assets/icon.png")}/>
<Text>Welcome to our application</Text>
<br></br>
<TextInput
placeholder="Your Email"
onChangeText={(text)=> {this.setState({ email: text})}}
/><br></br>
<TextInput
placeholder="Your Username"
onChangeText={(text)=> {this.setState({ username: text})}}
/><br></br>
<TextInput
placeholder="Your Password"
onChangeText={(text)=> {this.setState({ password: text})}}
/><br></br>
<Button title="Register" onPress={()=> this.submit()}/>
</View>
<TouchableOpacity style={styles.loginButton} onPress={()=> buttonFeedback(1)}>
<View><Text style={styles.text}>Log In</Text></View>
</TouchableOpacity>
<TouchableOpacity style={styles.registerButton} onPress={()=> buttonFeedback(2)}>
<View><Text style={styles.text}>Register</Text></View>
</TouchableOpacity>
</ImageBackground>
</>
);
}
}
export default Welcome;
const styles = StyleSheet.create({
background: {
flex: 1,
justifyContent: "flex-end",
alignItems: "center"
},
loginButton: {
width: '100%',
height: 70,
backgroundColor: '#fc5c65',
alignItems: 'center'
},
registerButton: {
width: '100%',
height: 70,
backgroundColor: '#4ecdc4',
alignItems: 'center'
},
logo: {
width: 100,
height: 100,
},
logoContainer: {
position: "absolute",
top: 70,
alignItems: "center"
},
text: {
color: 'white',
}
})
Can anyone tell me how to resolve this?

accessing this.props.navigation.state.params ouside render

I am passing a parameter from ListView to a detailed page. Can I access this parameter outside the render on my detailed page:
Below is my code to pass the parameter:
<ListView
dataSource={this.state.dataSource}
renderRow = {( rowData ) =>
<TouchableOpacity style = { styles.item } activeOpacity = { 0.4 } onPress = { this.clickedItemText.bind( this, rowData ) }>
<Text style = { styles.text }>{ rowData.ser }</Text>
</TouchableOpacity>
}
renderSeparator = {() =>
<View style = { styles.separator }/>
}
enableEmptySections = { true }
/>
</View>
clickedItemText( clickedItem )
{
this.props.navigation.navigate('Item', { item: clickedItem });
}
I can get the parameter value on my detailed page using the code below:
<View style = { styles.container2 }>
<Text style = { styles.text }>You Selected: { this.props.navigation.state.params.item.Location.toUpperCase() }</Text>
</View>
I need to do this.props.navigation.state.params.item.Location ouside render. The reason I want to do that because I want to create a ListView on my detailed page by filtering my Json data based on the passed parameter so for e.g. if the parameter passed is 2 then I want to filter my JSON data based on 2 and create another ListView.
As far as I know filtering of the JSON data can only be done outside render. I could be wrong though, I am new to react Native.
Below is my entire class for detailed page.
import React, { Component } from 'react';
import { StyleSheet, Text, View, ListView, ActivityIndicator, TextInput } from 'react-native';
import ServiceDetails from '../reducers/ServiceDetails';
class ServiceListDetails extends Component
{
constructor() {
super();
var newList = ServiceDetails.filter(obj => obj.fk === this.props.navigation.state.params.item.id);
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows(ServiceDetails),
};
}
static navigationOptions =
{
title: 'SecondActivity',
};
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
render()
{
return(
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) => <Text>{rowData.addr}</Text>}
/>
</View>
);
}
}
const styles = StyleSheet.create(
{
MainContainer:
{
justifyContent: 'center',
flex:1,
margin: 10
},
TextStyle:
{
fontSize: 23,
textAlign: 'center',
color: '#000',
},
rowViewContainer:
{
fontSize: 17,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
},
ActivityIndicator_Style:
{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
left: 0,
right: 0,
top: 0,
bottom: 0,
},
TextInputStyleClass:{
textAlign: 'center',
height: 40,
borderWidth: 1,
borderColor: '#009688',
borderRadius: 7 ,
backgroundColor : "#FFFFFF"
}
});
export default ServiceListDetails;
Below is screen shot of the error that I am getting on detailed page.
Below is the entire code of my Master Page that has a list View on it and it works fine:
import React, { Component } from 'react';
import { Text, View, StyleSheet, ListView, ActivityIndicator, TextInput, TouchableOpacity } from 'react-native';
import { Provider, connect } from 'react-redux';
import { createStore } from 'redux'
import reducers from '../reducers/ServiceReducer';
import ServiceItem from './ServiceItem';
import Icon from 'react-native-vector-icons/EvilIcons';
import ServiceDetail from './ServiceDetail';
import TestActivity from './TestActivity';
import { StackNavigator } from 'react-navigation';
import ServiceListDetails from './ServiceListDetails' ;
class AutoCompActivity extends Component {
constructor(props) {
super(props);
this.state = {
// Default Value of this State.
Loading_Activity_Indicator: true,
text:'',
}
this.arrayholder=[];
}
componentDidMount() {
const data = require('../reducers/services.json')
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
Loading_Activity_Indicator: false,
dataSource: ds.cloneWithRows(data),
}, function() {
// In this block you can do something with new state.
this.arrayholder = data ;
});
}
SearchFilterFunction(text){
const newData = this.arrayholder.filter(function(item){
const itemData = item.ser.toUpperCase()
const textData = text.toUpperCase()
return itemData.indexOf(textData) > -1
})
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newData),
text: text
})
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
/*Navigate_To_Second_Activity=(ser)=>
{
//Sending the JSON ListView Selected Item Value On Next Activity.
this.props.navigation.navigate('Second', { JSON_ListView_Clicked_Item: ser });
}*/
clickedItemText( clickedItem )
{
this.props.navigation.navigate('Item', { item: clickedItem });
}
static navigationOptions =
{
title: 'MainActivity',
};
render()
{
if (this.state.Loading_Activity_Indicator) {
return (
<View style={styles.ActivityIndicator_Style}>
<ActivityIndicator size = "large" color="#009688"/>
</View>
);
}
return (
<View style={styles.MainContainer}>
<TextInput
style={styles.TextInputStyleClass}
onChangeText={(text) => this.SearchFilterFunction(text)}
value={this.state.text}
underlineColorAndroid='transparent'
placeholder="Search Here"
/>
<ListView
dataSource={this.state.dataSource}
renderRow = {( rowData ) =>
<TouchableOpacity style = { styles.item } activeOpacity = { 0.4 } onPress = { this.clickedItemText.bind( this, rowData ) }>
<Text style = { styles.text }>{ rowData.ser }</Text>
</TouchableOpacity>
}
renderSeparator = {() =>
<View style = { styles.separator }/>
}
enableEmptySections = { true }
/>
</View>
);
}
}
export default MyNewProject= StackNavigator(
{
First: {screen: AutoCompActivity},
Item: {screen: ServiceListDetails}
}
);
const styles = StyleSheet.create(
{
MainContainer:
{
justifyContent: 'center',
flex:1,
margin: 10
},
TextStyle:
{
fontSize: 23,
textAlign: 'center',
color: '#000',
},
rowViewContainer:
{
fontSize: 17,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
},
ActivityIndicator_Style:
{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
left: 0,
right: 0,
top: 0,
bottom: 0,
},
TextInputStyleClass:{
textAlign: 'center',
height: 40,
borderWidth: 1,
borderColor: '#009688',
borderRadius: 7 ,
backgroundColor : "#FFFFFF"
},
separator:
{
height: 2,
backgroundColor: 'rgba(0,0,0,0.5)'
},
item:
{
padding: 15
},
text:
{
fontSize: 18
},
});
My services.json is below
[
{
"id":0,
"ser": "Test Service",
"Location": "TestLoc",
"Phone1":"(999)-999-5050",
"SecondLoc": "TestLoc2",
"email":"test#test.com",
"sourceLat":"33.977806",
"sourceLong":"-117.373261",
"destLatL1":"33.613355",
"destLongL1":"-114.596569",
"destLatL2":"33.761693",
"destLongL2":"-116.971169",
"destAddr1": "Test Address, Test Drive",
"destAddr2": "Test Address2, Test Drive2",
"onlineURL":"",
"Phone2": "(900)-900-3333"
}
]
My ServiceDetails.json is below:
[
{
"id":"1",
"fk": "0",
"addr": "2Test addr",
"phone": "(951)-955-6200",
"LatL":"33.935547",
"Long2":"-117.191",
"Online": ""
},
{
"id":"2",
"fk": "0",
"addr": "testaddr21",
"phone": "(999)-999-9999",
"LatL":"33.977880",
"Long2":"-117.1234",
"Online": ""
}
]
How can I achieve this?

React Native : Show parent component after closing a modal on child component

I have two components a Parent Component (App.js) and a Child Component (Logitem.js)
The parent component contains an array of child component and passes props to it.
The child component has a modal which is invoked upon clicking on a text element inside the child component.
The modal has a delete button which performs a delete operation on db.
All the above are working fine.
After the delete operation is performed I would like to show the parent component (aka) App.js but as of now the UI is still showing the modal on the child component.
How do we achieve that ?
Parent Component
import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView, Modal, DatePickerIOS } from 'react-native';
import {
dropLogsTable,
createLogsTable,
getProfileHeightStandardfromDB,
saveLogsRecord,
populateDummyLogs,
getLogsRecords,
getLogsRecordsFromDB,
neverendingmethod,
getLogsDetailsforSaveDelete
} from '../src/helper';
import { Spinner } from '../src/Spinner';
import Logitem from '../src/Logitem';
export default class App extends Component {
state = {
allLogs:{
rows:{
_array:[{logstringdate:''}]
}
},
profileobject: {profileheight: 100, profilestandard: "XYZ"},
showspinner: true,
count:0
};
componentDidMount() {
this.fetchProfileData();
this.getAllLogs();
}
renderSpinner() {
if(this.state.showspinner) {
return <Spinner size="small" />;
}
else {
//return this.state.allLogs.rows._array.map(ae => <Text>{ae.bmi}</Text>);
return this.state.allLogs.rows._array.map(
(ae) => (
<View
key={ae.logdate}
>
<Logitem
logstringdate={ae.logstringdate}
bmi={ae.bmi}
weight={ae.metricweight}
logdate={ae.logdate}
/>
</View>
)
);
}
}
async fetchProfileData() {
console.log('Before Profile Fetch');
const result = await getProfileHeightStandardfromDB();
console.log('After Profile Fetch');
console.log('Height : '+result.profileheight);
console.log('Standard: '+result.profilestandard);
this.setState({profileobject:result}); //Line Y
return result; //Line X
}
async getAllLogs() {
console.log('Before All Logs Fetch');
const allLogs = await getLogsRecordsFromDB();
console.log('After All Logs Fetch');
console.log('Spinner State ==>'+this.state.showspinner);
if(allLogs != null)
{
this.setState({allLogs, showspinner: false});
console.log('After async spinner state ==>'+this.state.showspinner);
console.log(allLogs);
}
return allLogs;
}
render() {
return (
<ScrollView style={styles.container}>
{this.renderSpinner()}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
top: {
width: '100%',
flex: 1,
},
bottom: {
flex: 1,
alignItems: 'center',
},
});
Child Component
import React, { Component } from 'react';
import { Text, View, Modal, DatePickerIOS, TextInput, Button } from 'react-native';
import {
deleteSelectedRecordDB
} from '../src/helper';
import { Spinner } from '../src/Spinner';
export default class Logitem extends Component {
constructor(props) {
super(props);
const { logstringdate, bmi, weight, logdate } = this.props;
}
state = {
selecteddate: '1',
selectedweight: this.props.weight,
showmodal: false,
date: new Date(86400000 * this.props.logdate),
}
async deleteSelectedRecord(){
console.log('Delete clicked');
console.log('this.state.selecteddate ==>' + this.state.selecteddate); //LINE X
const result = await deleteSelectedRecordDB(this.props.logdate);
console.log('deleteSelectedRecord after');
console.log('result ==> '+ result);
return result;
}
setModalVisible = (visible) => {
this.setState({showmodal: visible});
}
onWeightClick = () => {
this.setState({ selecteddate: this.props.logdate, showmodal: true }, () => {
console.log('Value in props==>' + this.props.logdate);
console.log('The selecteddate in the state ==> ' + this.state.selecteddate);
});
}
onDateChange(date) {
this.setState({
date: date
});
}
render() {
return (
<View style={styles.containerStyle}>
<Modal
animationType="slide"
transparent={false}
visible={this.state.showmodal}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={{marginTop: 22}}>
<DatePickerIOS
date={this.state.date}
mode="date"
onDateChange={(date) => this.onDateChange(date)}
style={{ height: 100, width: 300 }}
/>
</View>
<View style={{ marginTop: 22, borderColor: '#ddd', borderWidth: 5 }}>
<TextInput
returnKeyType="done"
keyboardType='numeric'
style={{
height: 40,
width: 60,
borderColor: 'gray',
borderWidth: 1,
}}
onChangeText={(text) => this.setState({ selectedweight: text })}
value={this.state.selectedweight.toString()}
/>
<Text>KG</Text>
<Button
title="Delete"
onPress={this.deleteSelectedRecord.bind(this)}
style={{ marginTop: 200 }}
/>
</View>
</Modal>
<View style={styles.headerContentStyle}>
<Text>{this.props.logstringdate}</Text>
<Text>{this.props.bmi}</Text>
</View>
<View style={styles.thumbnailContainerStyle}>
<Text onPress={this.onWeightClick}>{this.props.weight}</Text>
</View>
</View>
);
}
};
const styles = {
containerStyle: {
borderWidth: 1,
borderRadius: 2,
borderColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2},
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
marginLeft: 5,
marginRight: 5,
marginTop:10,
},
thumbnailContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10,
flexDirection: 'row'
},
headerContentStyle: {
flexDirection: 'column',
justifyContent: 'space-around'
},
};
-Simple in deleteSelectedRecord function call setModalVisible(false)

undefined is not a function (evaluating 'fetch('apiurl')')

I am using below versions
react-native-router-flux ^3.39.1
react-native 0.44.0
I expecting that will call API which I am using with "fetch"
Have used componentDidMount but it's showing another error
undefined is not an object (evaluating 'this._component.getScrollableNode')
But I am getting below error outputs
Steps to reproduce
Create three scene using router flux (In my case App, Login, Home)
Use ScrollView for creating the Login.js Create a button
using TouchableHighlight after that call the fetch with a function
using onPress like onPress={ () => this.fetchData() }
Below code, I am using for App.js
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
AsyncStorage,
} from 'react-native';
import Login from './components/Login'
import Register from './components/Register'
import Home from './components/Home'
import { Scene, Router, TabBar, Modal, Schema, Actions, Reducer, ActionConst } from 'react-native-router-flux'
const reducerCreate = params=>{
const defaultReducer = Reducer(params);
return (state, action)=>{
console.log("ACTION:", action);
return defaultReducer(state, action);
}
};
export default class App extends Component {
constructor(props, context) {
super(props, context);
this.state = {
logged: false,
loading: true,
};
};
componentWillMount(){
self = this;
AsyncStorage.getItem('token')
.then( (value) =>{
if (value != null){
this.setState({
logged: true,
loading: false,
});
}
else {
this.setState({
loading: false,
})
}
});
};
render() {
if (this.state.loading) {
return <View><Text>Loading</Text></View>;
}
return (
<Router>
<Scene hideNavBar={true} key="root">
<Scene key="logIn" component={Login} title="Login" initial={!this.state.logged}/>
<Scene key="regisTer" component={Register} title="Register"/>
<Scene key="home" component={Home} title="home" initial={this.state.logged}/>
</Scene>
</Router>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
And below code, using for Login.js
/* #flow */
import React, { Component } from 'react';
import {
View,
StyleSheet,
Image,
ScrollView,
TextInput,
Text,
TouchableHighlight,
Alert,
} from 'react-native';
import { Container, Content, InputGroup, Input, Icon, Item } from 'native-base';
import Button from 'react-native-button'
import {Actions} from 'react-native-router-flux'
import ResponsiveImage from 'react-native-responsive-image'
export default class Login extends Component {
constructor(props){
super(props)
this.state = {
email: '',
password: '',
data: '',
}
}
fetchData() {
fetch('http://allstariq.tbltechnerds.com/api/login/?username=andress&password=23434')
.then((response) => response.json())
.then((responseData) => {
this.setState({
data: responseData.movies,
});
})
.done();
}
render() {
return (
<View style={styles.container}>
<ScrollView>
<View style={ styles.logoContainer }>
<View style={{flexDirection: 'row',}}>
<ResponsiveImage
source={require('../assets/logo.png')}
initWidth="300"
initHeight="160" />
</View>
</View>
<View style={ styles.formContainer }>
<Item>
<Icon active name='mail' />
<Input
onChangeText={(text) => this.setState({email: text})}
value={this.state.email}
placeholder='Email'/>
</Item>
<Item>
<Icon active name='key' />
<Input
onChangeText={(text) => this.setState({password: text})}
value={this.state.password}
placeholder='Password'/>
</Item>
<TouchableHighlight
style={ styles.loginButton }
onPress={ () => this.fetchData() }>
<Text style={ styles.btnText}>Login</Text>
</TouchableHighlight>
</View>
<View style={ styles.bottomContainer }>
<Text style={ styles.cenText }>Dont worry if you haven't an account yet . . </Text>
<Text
style={ styles.blueText}
onPress={ Actions.regisTer }
>Register Now</Text>
</View>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
logoContainer: {
flex: .5,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
},
logoItem: {
width: null,
height: null,
resizeMode: 'cover',
},
formContainer: {
flex: 4,
padding: 10,
},
inputelm: {
marginBottom: 10,
backgroundColor: '#999',
borderWidth: 0,
fontSize: 20,
color: '#FFF',
fontFamily: 'AmaticSC-Bold',
},
loginButton: {
borderRadius: 3,
marginBottom: 20,
marginTop: 20,
paddingLeft: 10,
paddingRight: 10,
backgroundColor: '#2196f3',
elevation: 4,
},
signupButton: {
borderRadius: 3,
marginBottom: 20,
marginTop: 20,
paddingLeft: 10,
paddingRight: 10,
backgroundColor: '#7cb342',
elevation: 4,
},
btnText: {
textAlign: 'center',
color: '#FFF',
fontSize: 30,
lineHeight: 40,
},
blueText: {
textAlign: 'center',
color: '#2196f3',
fontSize: 20,
lineHeight: 40,
},
bottomContainer: {
flex: 1,
padding: 10,
},
cenText: {
textAlign: 'center',
fontSize: 16,
},
});
What is the actual way to use fetch with react-native-router-flux? I am new to react, please help me.
well, its a couple of months late but the problem here is that your fetchData method hasn't got access to this because when you declare a method like this:
fetchData() {
}
Under the hood react is creating a function this way:
this.fetchData = function() {
}
when you declare a function using the function keyword, everything between {} will have its own "this" and your method will not have access to the "this" of the component context.
That is the reason why you are getting the "undefined", because you are calling "this.setState" inside the promise returned by fetch, so the error is not fetch, but this.
To solve this issue you could just define your method this way:
fetchData = () => {
}
And because the functions defined with a fat arrow do not create their own scope, the component "this" will be available from inside your method.
Did you try maybe to import the library?
Import fetch from "fetch";
You have not imported the fetch function, import it from the node-fetch module like
import fetch from 'node-fetch'

Resources