React-Native : how show loading screen before list view populated - react-native

Here is my code .I am using ComponentwillMount Function for API and then using isLoading variable and accordingly displaying the particular view.But its doesnt work... its seems to be I done something wrong please took a glance and help me out I am new to react - native
const UserPage = React.createClass({
getInitialState() {
return {
dataSource: dataSource.cloneWithRows(dataList),
isLoading:true
}
},
componentWillMount() {
SharedPreferences.getItem("sender_id", (value) => {
let user_id = value;
let url = "BaseURL/fetchSendTokens?user_id="+user_id;
fetch(url, {
method: "GET",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((responseData) => {
if (responseData.responsecode === 1) {
dataList = responseData.data;
this.setState = ({
dataSource: this.state.dataSource.cloneWithRows(dataList),
isLoading:false,
})
}
else {
ToastAndroid.show('Please try again...', ToastAndroid.SHORT);
}
})
.catch(e => {
ToastAndroid.show('Please try again...', ToastAndroid.SHORT);
})
.done();
});
},
renderRow(rowData, sectionID,){
let currentView = (rowData.visitor_profileImageUrl)?
<Image
source={{uri:rowData.visitor_profileImageUrl}}
style={{height:40,width:40,margin:15,borderRadius:100}}
resizeMode="contain"/> :
<Image
source={userprofilepic}
style={{height:40,width:40,margin:15,borderRadius:100}}
resizeMode="contain"/>;
return <View key={ sectionID }>
<View style={{ flex: 1,height:70,flexDirection: 'row'}}>
<View>
{currentView}
</View>
<Text style={{fontSize : 18,marginTop:15,marginLeft:20,color:"black"}} >{ rowData.visitor_name }</Text>
</View>
</View>
},
render() {
let loadingGif = "URL-loading.gif";
let currentView = (this.state.isLoading)?<View style={styles.background}>
<View style={styles.markWrap}>
<Image source={{uri:loadingGif}} style={styles.verifyLogo} resizeMode="contain"/>
</View>
</View>:
<ListView dataSource={this.state.dataSource} renderRow={this.renderRow} enableEmptySections={true}/>;
return(
<View>
{currentView}
</View>
);
},
});

Your problem is a typo:
this.setState = ({
datasource: this.state.dataSource.cloneWithRows(dataList),
isLoading:false,
})
Should be:
this.setState = ({
dataSource: this.state.dataSource.cloneWithRows(dataList),
isLoading:false,
})
Note that you seem to keep around a global dataSource and dataList - that's usually not a good practice. If you need to keep data, use props and callbacks to pass it around, not globals.

constructor(props){
super(props);
this.state = {
loading: true,
}
}
render(){
if (this.props.loading) {
return (<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}><ActivityIndicator
animating={states.campaign.loading}
style={[styles.centering, { height: 80 }]}
size="large"
/></View>);
}else{
return (<ListView></ListView>);
}
}

Related

How to refresh a single item in a FlatList in React-Native?

I made a Like function with React and Flask API, it works pretty well, it makes the Like action but it only appears when I refresh the whole list. Somehow I want to refresh the Like picture and the Like count at the post.
I tried to put extraData in my FlatList but that does not solve my problem...
handleClick() {
const headers = {
'Authorization': 'jwt ' + this.props.jwt
};
const action = this.props.has_liked? 'unlike':'like'
axios.post("http://127.0.0.1:5000/API/likeaction",{
id: this.props.id,
action: action
}, {
headers: headers
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error)
});
this.setState({liked: action})
}
render() {
const img = this.props.has_liked? require('../assets/icons/heart-filled.png') : require('../assets/icons/heart-no-fill.png')
return(
<View style={{flex:1, marginTop: 10, marginBottom:16, left: 20}}>
<View style={{flex: 1, flexDirection: 'row'}}>
<Image source={this.props.image_uri} style={{height:42, width: 42, borderRadius:21}}/>
<Text style={{left:20,paddingTop:6}}>{this.props.author}</Text>
<Text style={{position: 'absolute', right: 40, paddingTop:6,fontSize:12,color:'#babbbc'}}> {this.props.date} </Text>
</View>
<View style={{flex:1, left: 60, right:20,width: '70%', marginTop:-10}}>
<Text style={{fontWeight:'bold',fontSize:18,marginBottom:6}}>{this.props.title} </Text>
<Text style={{fontSize:16,marginBottom:6 }}>{this.props.content}</Text>
<View style={{flex: 1, flexDirection: 'row'}}>
<TouchableOpacity onPress={this.handleClick}>
<Image style={{width:24, height:24, marginBottom:6, marginTop:6}} source={img} />
</TouchableOpacity>
<Text style={{paddingTop:10, marginLeft:6, fontSize:14,color:'#bfbfbf'}}>{this.props.likes}</Text>
</View>
</View>
</View>
);
}
}
<FlatList
data={this.state.dataSource}
extraData={this.state}
renderItem={({item}) => <PostView title={item.title}
content={item.content}
author={item.author}
date={item.date_posted}
likes={item.likes}
has_liked={item.has_liked}
jwt = {this.props.screenProps.jwt}
id = {item.id}
image_uri={{uri:'http://127.0.0.1:5000/static/profile_pics/'+item.profile_image}}/> }
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh}
keyExtractor={item => item.id}/>
</View>
extraData :
extraData={{this.state}}
and put this.setState({liked: action}) here:
.then((response) => {
console.log(response.data);
this.setState({liked: action})
})
try with in home
this.state = {
loading: true,
email: '',
error: '',
refreshing: false,
dataSource: [],
updated: false
}
handleChange = () => {
this.setState({ updated: true })
}
handleRefresh = () => {
this.setState({
refreshing: true,
data: this.state.dataSource
}, () => {
this.makeRemoteRequest()
})
}
Replace
<PostView title={item.title}
....
/>
with
<PostView title={item.title}
.....
handleChange={this.handleChange}/>
extraData={this.state}
and update
and
handleClick() {
const headers = {
'Authorization': 'jwt ' + this.props.jwt
};
axios.post("http://127.0.0.1:5000/API/likeaction",{
id: this.props.id,
}, {
headers: headers
})
.then((response) => {
console.log(response.data);
if(response.data.account == "liked"){
this.setState({liked:true})
}else{
this.setState({liked:false})
}
})
.catch((error) => {
console.log(error)
});
}
with
handleClick() {
const headers = {
'Authorization': 'jwt ' + this.props.jwt
};
axios.post("http://127.0.0.1:5000/API/likeaction",{
id: this.props.id,
}, {
headers: headers
})
.then((response) => {
console.log(response.data);
this.props.handleChange(true);
if(response.data.account == "liked"){
this.setState({liked:true})
}else{
this.setState({liked:false})
}
})
.catch((error) => {
console.log(error)
});
}
const img = this.state.liked? require('../assets/icons/heart-filled.png') : require('../assets/icons/heart-no-fill.png')
with
const img = this.state.liked ? require('../assets/icons/heart-filled.png') : require('../assets/icons/heart-no-fill.png')

Showing loading animation when clicking login button not working

I have the following code. I have two issues. First one, When I click the login button is shows the loading animation. But, it should toggle if the login process is success or fail. It's not working. Second one, If I do not add this line of code "this.toggleLoader = this.toggleLoader.bind(this);", the toggleLoader function show the error, this.setState is not a function. Please not that after log in successfully, the page navigate to new screen Home page. How can I toggle the loader before that ? If I call the function toggleLoader() after the if loop, not working.
import React, {Component} from 'react'
import {
Alert,
AsyncStorage,
Keyboard,
Text,
View,
TextInput,
TouchableHighlight, TouchableOpacity,
Image,
ActivityIndicator,
} from 'react-native'
import config from "../../../../config";
import styles from './style'
import {Icon} from "react-native-elements";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
credentials: {
email: "",
password: "",
},
loading: false,
};
this.toggleLoader = this.toggleLoader.bind(this);
}
updateText(text, field) {
let newCredentials = Object.assign(this.state.credentials);
newCredentials[field] = text;
this.setState = ({
credentials: newCredentials
})
}
toggleLoader() {
this.setState({
loading: !this.state.loading
});
}
async login() {
Keyboard.dismiss();
let credentials = this.state.credentials;
if (this.state.credentials.email == '' || this.state.credentials.password == '') {
Alert.alert("Please fill all the fields.");
} else {
const that = this;
credentials.email = that.state.credentials.email.toLowerCase();
// start loading when all fields are fill
this.setState({ loading: !this.state.loading });
fetch(config.baseURL + 'mobileapi/get_token/?username=' + `${that.state.credentials.email}` + '&password=' + `${that.state.credentials.password}`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
credentials: credentials,
}),
})
.then((response) => response.json())
.then(responseJson => {
//stop loading after successful response
this.setState({ loading: !this.state.loading });
if (responseJson.confirmation === "success") {
// alert(JSON.stringify(responseJson.data));
AsyncStorage.setItem('USER_ID', responseJson.data.user_id);
AsyncStorage.setItem('USER_NAME', responseJson.data.user_name);
AsyncStorage.setItem('USER_TYPE', responseJson.data.user_type);
AsyncStorage.setItem('FIRST_NAME', responseJson.data.first_name);
AsyncStorage.setItem('LAST_NAME', responseJson.data.last_name);
AsyncStorage.setItem('EMAIL', responseJson.data.user_email);
AsyncStorage.setItem('AUTHENTICATION_TOKEN', responseJson.data.token);
setTimeout(() => {
this.props.navigation.navigate("Home")
}, 500);
} else {
setTimeout(() => {
//code to handle an error
throw new Error(responseJson.message);
}, 500);
}
})
.catch((err) => {
//stop loading
this.setState({ loading: !this.state.loading });
setTimeout(() => {
if (JSON.stringify(err.message) === JSON.stringify('Network request failed')) {
alert('Please check your internet connection or try again later');
} else {
alert(JSON.stringify(err.message));
}
}, 500);
})
}
}
render() {
const loginText = (this.state.loader) ? 'Loading' : 'Login';
return (
<View style={styles.container}>
<Image source={require('../../../../assets/images/icons/logo.png')}
style={{width: 99, height: 99, margin: 5,}}/>
<Text style={{fontSize: 20, margin: 20, color: "#0aa1e2"}}>Test App</Text>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon}
source={require('../../../../assets/images/icons/username.png')}/>
<TextInput style={styles.inputs}
placeholder="Username"
keyboardType="email-address"
underlineColorAndroid='transparent'
onChangeText={text => {
this.updateText(text, 'email')
}} value={this.state.email}
autoCorrect={false}
autoCapitalize={"none"}
/>
</View>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon}
source={require('../../../../assets/images/icons/password.png')}/>
<TextInput style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid='transparent'
onChangeText={text => {
this.updateText(text, 'password')
}}
value={this.state.password}
autoCorrect={false}
secureTextEntry/>
</View>
<TouchableHighlight style={[styles.buttonContainer, styles.loginButton]}
onPress={this.login.bind(this)} >
<View style={{justifyContent: 'center', flex: 1, flexDirection: 'row'}}>
{this.state.loading === false ?
<Icon name='login' type='entypo' size={16} color='white'/> :
<ActivityIndicator size="small" color="#ffffff"/>}
<Text style={styles.loginText}> {loginText} </Text>
</View>
</TouchableHighlight>
</View>
);
}
}
export default Login;
I have updated your login() method. Please try it. It may help you.
async login() {
Keyboard.dismiss();
let credentials = this.state.credentials;
if (this.state.credentials.email == '' || this.state.credentials.password == '') {
Alert.alert("Please fill all the fields.");
} else {
credentials.email = that.state.credentials.email.toLowerCase();
// start loading when all fields are fill
this.toggleLoader();
fetch(config.baseURL + 'mobileapi/get_token/?username=' + `${that.state.credentials.email}` + '&password=' + `${that.state.credentials.password}`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
credentials: credentials,
}),
})
.then((response) => response.json())
.then(responseJson => {
//stop loading after successful response
this.toggleLoader();
if (responseJson.confirmation === "success") {
AsyncStorage.setItem('USER_ID', responseJson.data.user_id);
AsyncStorage.setItem('USER_NAME', responseJson.data.user_name);
AsyncStorage.setItem('USER_TYPE', responseJson.data.user_email);
AsyncStorage.setItem('AUTHENTICATION_TOKEN', responseJson.data.token);
setTimeout(() => {
this.props.navigation.navigate("Home")
}, 500);
} else {
setTimeout(() => {
//code to handle an error
}, 500);
}
})
.catch((err) => {
//stop loading
this.toggleLoader();
setTimeout(() => {
if (JSON.stringify(err.message) === JSON.stringify('Network request failed')) {
alert('Please check your internet connection or try again later');
} else {
alert(JSON.stringify(err.message));
}
}, 500);
})
}
}
You have set email in TextInput like this.state.email. this should be this.state.credentials.email. same things sholud be follow for password. change onPress event of render() method like this:
render() {
const loginText = (this.state.loader) ? 'Loading' : 'Login';
return (
<View style={styles.container}>
<Image source={require('../../../../assets/images/icons/logo.png')}
style={{width: 99, height: 99, margin: 5,}}/>
<Text style={{fontSize: 20, margin: 20, color: "#0aa1e2"}}>Test App</Text>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon}
source={require('../../../../assets/images/icons/username.png')}/>
<TextInput style={styles.inputs}
placeholder="Username"
keyboardType="email-address"
underlineColorAndroid='transparent'
onChangeText={text => {
this.updateText(text, 'email')
}}
value={this.state.credentials.email}
autoCorrect={false}
autoCapitalize={"none"}
/>
</View>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon}
source={require('../../../../assets/images/icons/password.png')}/>
<TextInput style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid='transparent'
onChangeText={text => {
this.updateText(text, 'password')
}}
value={this.state.credentials.password}
autoCorrect={false}
secureTextEntry/>
</View>
<TouchableHighlight style={[styles.buttonContainer, styles.loginButton]}
onPress={this.login.bind(this)} >
<View style={{justifyContent: 'center', flex: 1, flexDirection: 'row'}}>
{this.state.loading === false ?
<Icon name='login' type='entypo' size={16} color='white'/> :
<ActivityIndicator size="small" color="#ffffff"/>}
<Text style={styles.loginText}> {loginText} </Text>
</View>
</TouchableHighlight>
</View>
);
}
TypeError: this.setState is not a function. This error is coming from updateText() method.you have added = during setState, which is throwing the error.
updateText(text, field) {
let newCredentials = Object.assign(this.state.credentials);
newCredentials[field] = text;
// setState should be done like this
this.setState({
credentials: newCredentials
})
}

How to pass data from screen to screen from flat list item

How do i able to pass the list items from first screen to the third screen, i am able to pass data on to the second screen but not the third screen. What i'm trying to achieve is how do i able to edit the list item on the third screen and inside the edit text input get the data and update. By the way, i'm using flat list item, because list view is deprecated. Below are my codes and screenshots.
First Screenshot
Second screenshot
Third screenshot
First screenshot coding
class SecondScreen extends Component {
constructor(props){
super(props);
this.state = {
loading: true,
email: '',
name: '',
title: '',
description: '',
error: '',
dataSource: [],
isFetching: false
}
}
onPress(item){
this.props.navigation.navigate(
'DetailsScreen',
{item},
);
}
renderItem = ({ item }) => {
return (
<TouchableOpacity style={{ flex: 1, flexDirection: 'row',
marginBottom: 3}}
onPress={() => { this.onPress(item) }}>
<View style={{ flex: 1, justifyContent: 'center', marginLeft:
5}}>
<Text style={{ fontSize: 18, color: 'green', marginBottom:
15}}>
{"ID - "+item.id}
</Text>
<Text style={{ fontSize: 18, color: 'green', marginBottom:
15}}>
{"Title - "+item.title}
</Text>
<Text style={{ fontSize: 16, color: 'red'}}>
{"Description - "+item.description}
</Text>
</View>
</TouchableOpacity>
)
}
renderSeparator = () => {
return (
<View
style={{height: 1, width: '100%', backgroundColor: 'black'}}>
</View>
)
}
ListEmptyView = () => {
return (
<View style={styles.container}>
<Text style={{textAlign: 'center'}}> No job available.</Text>
</View>
);
}
handleBackButton = () => {
Alert.alert(
'Exit App',
'Exiting the application?', [{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel'
}, {
text: 'OK',
onPress: () => BackHandler.exitApp()
},],{
cancelable: false
}
)
return true;
}
componentDidMount(){
this.getAvailableJob()
BackHandler.addEventListener('hardwareBackPress',
this.handleBackButton);
}
getAvailableJob() {
const headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + this.props.token
};
axios({
method: 'GET',
url: 'http://192.168.1.201:8000/api/jobs',
headers: headers,
}).then((response) => {
console.log('response3',response)
console.log('response4',this.props.token)
this.setState({
dataSource: response.data,
isFetching: false
});
}).catch((error) => {
console.log(error);
this.setState({
error: 'Error retrieving data',
loading: false
});
});
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress',
this.handleBackButton);
}
onRefresh() {
this.setState({ isFetching: true }, function() { this.getAvailableJob()
});
}
render() {
const { container, emailText, errorText } = styles;
const { loading, email, name, error, title, description } = this.state;
return(
<View style={container}>
<FlatList
data={this.state.dataSource}
onRefresh={() => this.onRefresh()}
refreshing={this.state.isFetching}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
ListEmptyComponent={this.ListEmptyView}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>
);
}
}
export default withNavigation(SecondScreen);
Second screenshot coding
class DetailsScreen extends React.Component {
handleBackButton = () => {
this.props.navigation.popToTop();
return true;
}
componentDidMount(){
BackHandler.addEventListener('hardwareBackPress',
this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress',
this.handleBackButton);
}
onPress(item){
this.props.navigation.push(
'EditDetailsScreen',
{item},
);
}
render() {
const { backButton } = styles;
let item = this.props.navigation.state.params.item;
return (
<View style={styles.container}>
<View style={[styles.container2, { backgroundColor: 'yellow' },
styles.hiddenContainer]}>
<Text style = { styles.TextStyle }> ID {
this.props.navigation.state.params.item.id }</Text>
</View>
<Text style = { styles.TextStyle }> Title {
this.props.navigation.state.params.item.title }</Text>
<Text style = { styles.TextStyle }> Description {
this.props.navigation.state.params.item.description }</Text>
<TouchableOpacity
style = {styles.submitButton}
onPress = {() => { this.onPress(item) }}>
<Text style = {styles.submitButtonText}> Edit </Text>
</TouchableOpacity>
</View>
);
}
}
export default withNavigation(DetailsScreen);
Third screenshot coding
class EditDetailsScreen extends React.Component {
handleTitle = (text) => {
this.setState({ title: text })
}
handleDescription = (text) => {
this.setState({ description: text })
}
handleBackButton = () => {
this.props.navigation.popToTop();
return true;
}
componentDidMount(){
BackHandler.addEventListener('hardwareBackPress',
this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress',
this.handleBackButton);
}
updateJobDetails = () => {
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + this.props.token
};
axios({
method: 'PUT',
url: 'http://192.168.1.201:8000/api/jobs',
headers: headers,
}).then((response) => {
this.setState({
title: response.data,
description: response.data,
loading: false
});
}).catch((error) => {
console.log(error);
this.setState({
error: 'Error retrieving data',
loading: false
});
});
}
render() {
return (
<View style={styles.container}>
<View style={[styles.container2, { backgroundColor: 'yellow' },
styles.hiddenContainer]}>
<Text style = { styles.TextStyle }> ID {
this.props.navigation.state.params.item.id }</Text>
</View>
<Text style = { styles.TextStyle }> Title {
this.props.navigation.state.params.item.title }</Text>
<Text style = { styles.TextStyle }> Description {
this.props.navigation.state.params.item.description }</Text>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Edit Title"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handleTitle}/>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Edit Description"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
onChangeText = {this.handleDescription}/>
<TouchableOpacity
style = {styles.submitButton}
onPress = {this.updateJobDetails}>
<Text style = {styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}
}
export default withNavigation(EditDetailsScreen);
I can update using postman but not in react native, and also in postman i had to set the Body to use x-www-form-urlencoded instead of form-data. So how do i able to update in react native? Any help would be much appreciated. Below is my postman screenshot.
Postman
A suggestion is to use a state container like react-redux, but if you don't want: you can pass a function in the props like
<renderedItem update={(newVal) => this.setState({ val: newVal})}>
and then in the renderedItem you can call this function with new value like so:
this.props.update(this.state.newVal)
I've solved the problem by using qs.stringify(data). Below is my updated code.
updateJobDetails = () => {
url = 'http://192.168.1.201:8000/api/jobs/' + this.props.navigation.state.params.item.id;
const qs = require('qs');
const data = {title:this.state.TextInput_Title,
description:this.state.TextInput_Description};
const options = {
method: 'PUT',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ' + this.props.token
},
data: qs.stringify(data),
url
}
axios(options).then((response) => {
console.log('update response',response)
Alert.alert(
'Update successful',
'Your details has been updated', [{
text: 'OK',
onPress: () => this.props.navigation.popToTop()
},]
,{
cancelable: false
}
)
this.setState({
loading: false,
});
}).catch((error) => {
Alert.alert("Please Enter All the Values.");
console.log(error);
this.setState({
error: 'Error retrieving data',
loading: false
});
});
}
render() {
return (
<View style={styles.container}>
<View style={[styles.container2, { backgroundColor: 'yellow' },
styles.hiddenContainer]}>
<Text style = { styles.TextStyle }> ID {
this.props.navigation.state.params.item.id }</Text>
</View>
<Text style = {styles.TextStyle2}>
Title:
</Text>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Edit Title"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
value={this.state.TextInput_Title}
onChangeText = { TextInputValue => this.setState({TextInput_Title: TextInputValue})}/>
<Text style = {styles.TextStyle2}>
Description:
</Text>
<TextInput style = {styles.input}
underlineColorAndroid = "transparent"
placeholder = "Edit Description"
placeholderTextColor = "#9a73ef"
autoCapitalize = "none"
value={this.state.TextInput_Description}
onChangeText = { TextInputValue =>
this.setState({TextInput_Description: TextInputValue})}/>
<TouchableOpacity
style = {styles.submitButton}
onPress = {this.updateJobDetails}>
<Text style = {styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}

TouchableOpacity onpress not working react native listview

I am using list view inside the tabvewAnimated. Right now I am facing problem while adding the onPress() TouchableOpacity to row where its get automatically triggered whenever page loads andwhen i added this.props.navigator.push({id: 8,}); it giving me error "undefined is not object(evaluating 'this.props.navigator.push')" I am using Navigator and building the app on android
Here is my code:
const RecievedPage = React.createClass({
getInitialState() {
let dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.guid != r2.guid});
return {
dataSource: dataSource.cloneWithRows(dataList),
loader:true,
}
},
display(rowData){
this.props.navigator.pop();
ToastAndroid.show(rowData+"", ToastAndroid.SHORT);
},
componentWillMount() {
let self = this;
SharedPreferences.getItem("sender_id", (value) => {
let user_id = value;
let url = BASE_URL;
fetch(url, {
method: "GET",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((responseData) => {
if (responseData.responsecode === 1) {
Received = responseData.data;
if (Received.length === 0) {
ToastAndroid.show("No Data found", ToastAndroid.SHORT);
}else{
self.setState({dataSource:this.state.dataSource.cloneWithRows(Received), loader:false});
}
}
else {
ToastAndroid.show('please try again...', ToastAndroid.SHORT);
}
})
.catch(e => {
// ToastAndroid.show('Error:Please try again...', ToastAndroid.SHORT);
})
.done();
});
},
renderRow(rowData, sectionID,rowID){
let QrView = (rowData.qrImageUrl!== "")?
<TouchableOpacity activeOpacity={.5} onPress={() => this.display(rowData.qrImageUrl)} >
<Image
source={{uri:rowData.qrImageUrl}}
style={{height:40,width:40,margin:15}}
resizeMode="contain"/>
</TouchableOpacity>
:
<Text style={{fontSize : 18,marginTop:15,color:"black",margin:15}} >NA</Text>;
return <View key={sectionID}>
<View style={{ flex: 1,height:70,flexDirection: 'row',justifyContent: 'space-between'}}>
<Text style={{fontSize : 18,marginTop:15,color:"black"}} >{rowData.sender_name}</Text>
<View>
{QrView}
</View>
</View>
</View>
},
render() {
return(
<ListView dataSource={this.state.dataSource}
renderRow={this.renderRow}
enableEmptySections={true}
style={{backgroundColor:"white", }}/>
);
},
});
You are calling the function instead of passing a function.
This:
<TouchableOpacity activeOpacity={.5} onPress={this.display(rowData.qrImageUrl)}>
Should be:
<TouchableOpacity activeOpacity={.5} onPress={() => this.display(rowData.qrImageUrl)}>

Fetch -React Native.Error:on function

undefined is not a function (evaluating 'this_submitForm()')....*I am getting this error while calling the function.I am new to react native and I have searched Every where But i didn't get any solution.If solution available please add sample code for better understanding.
I am posting my code here:*
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity,
} = React;
var SCREEN_WIDTH = require('Dimensions').get('window').width;
var PageOne = React.createClass({
onEmailChange(email) {
let s = this.state;
s.email = email;
this.setState(s);
},
render() {
return (
<View style={[styles.container, {backgroundColor: 'green'}]}>
<Text style={styles.welcome}>Greetings!</Text>
<TouchableOpacity onPress={this._handlePress}>
<View style={{paddingVertical: 10, paddingHorizontal: 20, backgroundColor: 'black'}}>
<TextInput
onChangeText={this.onEmailChange}
placeholderTextColor="#a0a0a0"
placeholder="email"
underlineColorAndroid='transparent'/>
</View>
</TouchableOpacity onPress={this._submitForm()}>
</View>
)
},
});
var PageTwo = React.createClass({
render() {
return (
<View style={[styles.container, {backgroundColor: 'green'}]}>
<Text style={styles.welcome}>Greetings!</Text>
<TouchableOpacity onPress={this._handlePress}>
<View style={{paddingVertical: 10, paddingHorizontal: 20, backgroundColor: 'black'}}>
<Text style={styles.welcome}>Go to page two</Text>
</View>
</TouchableOpacity>
</View>
)
},
});
class VerifyMe extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
}
}
_renderScene(route, navigator) {
if (route.id === 1) {
return <PageOne navigator={navigator}/>
} else if (route.id === 2) {
return <PageTwo navigator={navigator}/>
}
}
_submitForm() {
fetch(baseURL+'users/loginUser', {
method: 'post',
body: JSON.stringify({
config_name: 'default',
email: this.state.email,
})
.then((response) => response.json())
.then((responseJson) => {
if (response.data.responsecode === 1) {
this.props.navigator.push({id: 2,});
}
})
.catch((error) => {
console.error(error);
})
});
}
render() {
return (
);
}
}
You are trying to use this._submitFrom in PageOne but you defined it in PageTwo, try to use following code
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
Navigator,
TouchableOpacity,
} = React;
var SCREEN_WIDTH = require('Dimensions').get('window').width;
var PageOne = React.createClass({
getInitialState () {
return {
email:'', //add your initial state for this class here
};
},
onEmailChange(email) {
//let s = this.state;
//s.email = email; // no need of these lines
this.setState({
email:email
});
},
_submitForm() {
fetch(baseURL+'users/loginUser', {
method: 'post', body: JSON.stringify({ config_name: 'default', email: this.state.email
})
.then((response) => response.json())
.then((responseJson) => {
if (response.data.responsecode === 1) {
this.props.navigator.push({id: 2,});
}
})
.catch((error) => {
console.error(error);
})
});
}
render() {
return (
<View style={[styles.container, {backgroundColor: 'green'}]}>
<Text style={styles.welcome}>Greetings!</Text>
<TouchableOpacity onPress={this._handlePress}>
<View style={{paddingVertical: 10, paddingHorizontal: 20, backgroundColor: 'black'}}>
<TextInput
onChangeText={this.onEmailChange}
placeholderTextColor="#a0a0a0"
placeholder="email"
underlineColorAndroid='transparent'/>
</View>
</TouchableOpacity onPress={this._submitForm.bind(this)}> //need to use bind
</View>
)
},
});
var PageTwo = React.createClass({
render() {
return (
<View style={[styles.container, {backgroundColor: 'green'}]}>
<Text style={styles.welcome}>Greetings!</Text>
<TouchableOpacity onPress={this._handlePress}>
<View style={{paddingVertical: 10, paddingHorizontal: 20, backgroundColor: 'black'}}>
<Text style={styles.welcome}>Go to page two</Text>
</View>
</TouchableOpacity>
</View>
)
},
});
class VerifyMe extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
}
}
_renderScene(route, navigator) {
if (route.id === 1) {
return <PageOne navigator={navigator}/>
} else if (route.id === 2) {
return <PageTwo navigator={navigator}/>
}
}
} render() { return ( ); } }