Fetch -React Native.Error:on function - react-native

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 ( ); } }

Related

Understand error : Cannot update a component from inside the function body of a different component

I have this error and I don't understand where it came from.
I'm trying to set up a screen where I scan products and when it's done, I redirect to another page.
Could you help me identify the problem and why it behaves like this?
the error is :
Warning: Cannot update a component from inside the function body of a
different component.
My Code :
class Scan extends Component {
constructor(props) {
super(props);
this.state = {
Press: false,
hasCameraPermission: null,
reference: '',
displayArray: []
};
}
initListData = async () => {
let list = await getProducts(1);
if (list) {
this.setState({
displayArray: list,
});
}
};
async UNSAFE_componentWillMount() {
this.initListData();
if (parseInt(this.state.reference) > 0) {
let product_data = await getProductByRef(this.state.reference);
console.log(this.state.reference);
if (product_data && product_data.reference_id && parseInt(product_data.reference_id) > 0) {
this.props.navigation.navigate('ProductDetails', {reference : parseInt(this.state.displayArray.reference)})
} else {
this.props.navigation.goBack();
}
} else {
this.props.navigation.goBack();
}
};
componentDidMount() {
this.getPermissionsAsync();
}
getPermissionsAsync = async () => {
const { status } = await Permissions.askAsync(Permissions.CAMERA);
this.setState({ hasCameraPermission: status === "granted" });
};
_onPress_Scan = () => {
this.setState({
Press: true
});
}
handleBarCodeScanned = ({ type, data }) => {
this.setState({ Press: false, scanned: true, lastScannedUrl: data });
};
renderBarcodeReader = () => {
const { hasCameraPermission, scanned } = this.state;
if (hasCameraPermission === null) {
return <Text>{i18n.t("scan.request")}</Text>;
}
if (hasCameraPermission === false) {
return <Text>{i18n.t("scan.noaccess")}</Text>;
}
return (
<View
style={{
flex: 1,
flexDirection: "column",
justifyContent: "flex-end",
}}
>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : this.handleBarCodeScanned}
style={{ flex:1, ...StyleSheet.absoluteFillObject}}
/>
{scanned && (
<Button
title={"Tap to Scan Again"}
onPress={() => this.setState({ scanned: false })}
/>
)}
<Button
color="#F78400"
title= {i18n.t("scan.details")}
onPress={() => this.props.navigation.navigate('ProductDetails', {reference : parseInt(this.state.displayArray.reference)})}>{i18n.t("scan.details")}
</Button>
</View>
);
}
render() {
const { hasCameraPermission, scanned, Press } = this.state;
let marker = null;
console.log('displayArray', this.state.displayArray, 'reference', this.state.displayArray.reference)
return (
<View style={{flex:1}}>
<KeyboardAvoidingView behavior="padding" enabled style={{flex:1}}>
<ScrollView contentContainerStyle={{flexGrow: 1}} >
{Press ? (
<View style={{flex:1}}>
{this.renderBarcodeReader()}
</View>
) : (
<View style={{flex:1, justifyContent:'center', alignItems:'center'}}>
<TouchableOpacity
onPress={this._onPress_Scan}
activeOpacity={3}
>
<Text style={styles.viewDetails}>Scan BarCode</Text>
</TouchableOpacity>
</View>
)}
</ScrollView>
</KeyboardAvoidingView>
</View>
);
}
}
export default Scan;

Searching in Expo's FlatList

I used this tutorial but it didn't work (if you are interested, check out my last post). Any suggestions to make a working search for a flatlist?
I have a list of 100 things and just by inserting the name in a search bar, the flatlist should update with the results.
Try using react-native-searchable-flatlist
import React, { Component } from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import { ListItem, SearchBar } from 'react-native-elements';
class FlatListDemo extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
};
this.arrayholder = [];
}
componentDidMount() {
this.makeRemoteRequest();
}
makeRemoteRequest = () => {
const url = `https://randomuser.me/api/?&results=20`;
this.setState({ loading: true });
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: res.results,
error: res.error || null,
loading: false,
});
this.arrayholder = res.results;
})
.catch(error => {
this.setState({ error, loading: false });
});
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: '86%',
backgroundColor: '#CED0CE',
marginLeft: '14%',
}}
/>
);
};
searchFilterFunction = text => {
this.setState({
value: text,
});
const newData = this.arrayholder.filter(item => {
const itemData = `${item.name.title.toUpperCase()} ${item.name.first.toUpperCase()} ${item.name.last.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
this.setState({
data: newData,
});
};
renderHeader = () => {
return (
<SearchBar
placeholder="Type Here..."
lightTheme
round
onChangeText={text => this.searchFilterFunction(text)}
autoCorrect={false}
value={this.state.value}
/>
);
};
render() {
if (this.state.loading) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={{ flex: 1 }}>
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
leftAvatar={{ source: { uri: item.picture.thumbnail } }}
title={`${item.name.first} ${item.name.last}`}
subtitle={item.email}
/>
)}
keyExtractor={item => item.email}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
export default FlatListDemo;

React Native Select Contacts Checkmark with FlatList

I'm new to react native and i am trying to make a contacts checkmark from FlatList with Large data items.
We can select one or more items and I want to pass these all selected contacts to another screen when i clicked on DONE button ..
like this in the picture
React Code
import React, { Component } from 'react'
import {
View,
Text,
Dimensions,
TouchableOpacity,
FlatList,
ActivityIndicator,
Image,
TextInput,
PermissionsAndroid,
Platform,
} from 'react-native'
import Feather from "react-native-vector-icons/Feather"
import ContactsLib from 'react-native-contacts'
import { styles } from './ContactStyles'
import PropTypes from 'prop-types'
export class Contacts extends Component {
static navigationOptions = ({navigation}) => {
return {
headerTitle: () => (
<View style={{flex: 1, alignSelf: 'center'}}>
<Text style={{
color: '#fff',
alignSelf: 'center',
fontSize: 22,
}}>Contacts</Text>
</View>
),
headerRight: () => (
<TouchableOpacity onPress={() => navigation.goBack(null)}
style={{right: Platform.OS === 'ios' ? Dimensions.get("window").height < 667 ? '10%' : '5%' : '25%', backgroundColor: 'black', paddingLeft: 15}}>
<Text style={{fontSize: 18, color: '#fff'}}>Done</Text>
</TouchableOpacity>
),
headerLeft: () => (
<TouchableOpacity onPress={() => navigation.goBack(null)} style={{left: Dimensions.get("window").height < 667 ? '8%' : '3%', backgroundColor: 'black', width: '100%'}}>
<Feather style = {{paddingLeft : 10}} name="chevron-left" size={26} color="white" />
</TouchableOpacity>
),
headerStyle: {
backgroundColor: 'black',
},
headerTintColor: '#fff',
};
};
constructor(props) {
super(props)
this.state = {
contactList: [],
selectedContact: [],
text: '',
isLoading: true,
}
this.arrayholder = []
}
async componentDidMount() {
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
title: 'App Contact Permission',
message: 'This App needs access to your contacts ',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.getListOfContacts()
} else {
this.setState({ isLoading: false })
this.getOtherContacts()
}
} catch (err) {
this.setState({ isLoading: false })
}
} else {
ContactsLib.checkPermission((err, permission) => {
if (permission === 'denied') {
this.setState({ isLoading: false })
this.getOtherContacts()
} else {
this.getListOfContacts()
}
})
}
}
// Mics Method
getOtherContacts = () => {
const { otherContactList } = this.props
const arrFinal = []
if (otherContactList.length > 0) {
otherContactList.map((listItem) => {
arrFinal.push(listItem)
})
}
arrFinal.map((listItem, index) => {
listItem.isSelected = false
listItem.id = index
})
this.setState({ contactList: arrFinal, isLoading: false })
this.arrayholder = arrFinal
}
getListOfContacts = () => {
const { otherContactList } = this.props
const arrFinal = []
ContactsLib.getAll((err, contacts) => {
if (err) {
throw err
}
contacts.map((listItem) => {
arrFinal.push({
fullname: listItem.givenName + ' ' + listItem.familyName,
phoneNumber: listItem.phoneNumbers.length > 0 ? listItem.phoneNumbers[0].number : '',
avatar: listItem.thumbnailPath,
})
})
if (otherContactList.length > 0) {
otherContactList.map((listItem) => {
arrFinal.push(listItem)
})
}
arrFinal.map((listItem, index) => {
listItem.isSelected = false
listItem.id = index
})
this.setState({ contactList: arrFinal, isLoading: false })
this.arrayholder = arrFinal
})
}
getSelectedContacts = () => {
const { selectedContact } = this.state
return selectedContact
}
checkContact = (item) => {
const { onContactSelected, onContactRemove } = this.props
let arrContact = this.state.contactList
let arrSelected = this.state.selectedContact
arrContact.map((listItem) => {
if (listItem.id === item.id) {
listItem.isSelected = !item.isSelected
}
})
if (item.isSelected) {
arrSelected.push(item)
if (onContactSelected) {
onContactSelected(item)
}
} else {
if (onContactRemove) {
onContactRemove(item)
}
arrSelected.splice(arrSelected.indexOf(item), 1)
}
this.setState({ contactList: arrContact, selectedContact: arrSelected })
}
checkExist = (item) => {
const { onContactRemove } = this.props
let arrContact = this.state.contactList
let arrSelected = this.state.selectedContact
arrContact.map((listItem) => {
if (listItem.id === item.id) {
listItem.isSelected = false
}
})
if (onContactRemove) {
onContactRemove(item)
}
arrSelected.splice(arrSelected.indexOf(item), 1)
this.setState({ contactList: arrContact, selectedContact: arrSelected })
}
SearchFilterFunction = (text) => {
let newArr = []
this.arrayholder.map(function(item) {
const itemData = item.fullname.toUpperCase()
const textData = text.toUpperCase()
if (itemData.indexOf(textData) > -1) {
newArr.push(item)
}
})
this.setState({
contactList: newArr,
text: text,
})
}
//Render Method
_renderSeparator = () => {
const { sepratorStyle } = this.props
return <View style={[styles.sepratorStyle, sepratorStyle]} />
}
_renderItem = ({ item }) => {
const { viewCheckMarkStyle } = this.props
return (
<TouchableOpacity onPress={() => this.checkContact(item)}>
<View style={styles.viewContactList}>
<Image
source={item.avatar !== '' ? { uri: item.avatar } : require('./Resources/user.png')}
style={styles.imgContactList}
/>
<View style={styles.nameContainer}>
<Text style={styles.txtContactList}>{item.fullname}</Text>
<Text style={styles.txtPhoneNumber}>{item.phoneNumber}</Text>
</View>
{item.isSelected && (
<Image
source={require('./Resources/check-mark.png')}
style={[styles.viewCheckMarkStyle, viewCheckMarkStyle]}
/>
)}
</View>
</TouchableOpacity>
)
}
_renderItemHorizontal = ({ item }) => {
const { viewCloseStyle } = this.props
return (
<View style={styles.viewSelectedContactList}>
<Image
source={item.avatar !== '' ? { uri: item.avatar } : require('./Resources/user.png')}
style={styles.imgSelected}
/>
<TouchableOpacity
onPress={() => this.checkExist(item)}
style={[styles.viewCloseStyle, viewCloseStyle]}
>
<Image source={require('./Resources/error.png')} style={styles.imgCancelStyle} />
</TouchableOpacity>
<Text style={styles.txtSelectedContact} numberOfLines={1}>
{item.fullname}
</Text>
</View>
)
}
render() {
const { searchBgColor, searchPlaceholder, viewSepratorStyle } = this.props
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<View style={[styles.viewSearch, { backgroundColor: searchBgColor }]}>
<TextInput
style={styles.searchInput}
placeholder={searchPlaceholder}
onChangeText={this.SearchFilterFunction}
/>
</View>
<View>
<FlatList
showsHorizontalScrollIndicator={false}
data={this.state.selectedContact}
extraData={this.state}
renderItem={this._renderItemHorizontal}
horizontal
/>
</View>
{this.state.selectedContact.length > 0 && (
<View style={[styles.viewSepratorStyle, viewSepratorStyle]} />
)}
{this.state.contactList.length > 0 && (
<FlatList
ListFooterComponent={this._renderSeparator}
ItemSeparatorComponent={this._renderSeparator}
showsVerticalScrollIndicator={false}
data={this.state.contactList}
renderItem={this._renderItem}
onEndReachedThreshold={0.3}
extraData={this.state}
keyExtractor={(item) => item.id.toString()}
/>
)}
{this.state.isLoading && (
<View style={styles.loading}>
<ActivityIndicator animating={true} size="large" color="gray" />
</View>
)}
</View>
)
}
}
StyleSheet
Contacts.propTypes = {
otherContactList: PropTypes.array,
viewCloseStyle: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
viewCheckMarkStyle: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
sepratorStyle: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
viewSepratorStyle: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
searchBgColor: PropTypes.string,
searchPlaceholder: PropTypes.string,
onContactSelected: PropTypes.func,
onContactRemove: PropTypes.func,
}
Contacts.defaultProps = {
otherContactList: [],
viewCloseStyle: {},
viewCheckMarkStyle: {},
sepratorStyle: {},
viewSepratorStyle: {},
searchBgColor: 'rgb(202,201,207)',
searchPlaceholder: 'Search...',
onContactSelected: () => {},
onContactRemove: () => {},
}
export default Contacts
Please Help me..
Thanks.....

using classes and rendering api call in React Native

I am totally new in React Native, I am having problem rendering data from API call. When I do it inside function it is working for me when I am using useEffect... but in the Class I cannot use that.
Here is example of my code...
export default class Categories extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
};
}
componentDidMount() {
this.regionsGetRequest();
}
regionsGetRequest = () => {
this.setState({ loading: true });
const fetchData = async () => {
const result = await axios(
'https://...........json'
);
this.setState({
data: result.data,
error: result.error || null,
loading: false,
});
};
fetchData();
};
renderCategories = () => {
const categoryLive = this.state.data;
console.log(JSON.stringify(categoryLive));
I am getting in console: undefined, undefined... and then results as they should... like it is running 3 times for some reason... if I try to put above renderCategories:
componentDidMount() {
renderCategories();
}
I am getting just one undefined... when I connect variable categoryLive nothing is loading.
Sorry I have been strugling with this one... any help is really appreciated!!
No matter what I do, I am always getting 3 calls... first two empty object [], and third I get real results dumped in console. So my categories are not rendering.. they are empty.
Here is updated code, and I am posting whole file, it might ring some bells.
export default class Categories extends React.Component {
state = {
myData: [],
};
componentDidMount() {
axios
.get('https://..............json')
.then((res) => {
const myData = res.data;
this.setState({ myData });
});
}
renderCategories = () => {
const categoryLive = this.state.myData;
console.log(JSON.stringify(categoryLive));
const { navigation, route } = this.props;
const tabId = route.params?.tabId;
const categories = tabId
? categoryLive[tabId]
: categoryLive.victoria_bc;
//console.log(route.params?.tabId);
return (
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.categoryList}
>
<Block flex>
{categories.map((category) => (
<TouchableWithoutFeedback
key={`category-${category.id}`}
onPress={() => navigation.navigate('Category', { ...category })}
>
<Block flex card style={[styles.category, styles.shadow]}>
<ImageBackground
source={{ uri: category.image }}
style={[
styles.imageBlock,
{ width: width - theme.SIZES.BASE * 2, height: 252 },
]}
imageStyle={{
width: width - theme.SIZES.BASE * 2,
height: 252,
}}
>
<Block style={styles.categoryTitle}>
<Text size={18} bold color={theme.COLORS.WHITE}>
{category.title}
</Text>
</Block>
</ImageBackground>
</Block>
</TouchableWithoutFeedback>
))}
</Block>
</ScrollView>
);
};
render() {
return (
<Block flex center style={styles.categories}>
{this.renderCategories()}
</Block>
);
}
}
When I put it like this: I am getting default category ( and all data just fine... ) but my navigation is not working any more... (route.params?.tabId is not updating)
axios
.get('https://.............json')
.then((res) => {
this.setState({
myData: res.data,
error: res.error || null,
loading: false,
});
console.log('inside .then----' + JSON.stringify(this.state.myData));
const { navigation, route } = this.props;
const tabId = route.params?.tabId;
const tmpCategories = tabId
? this.state.myData[tabId]
: this.state.myData.victoria_bc;
this.setState({ categories: tmpCategories });
//console.log(route.params?.tabId);
});
If I put it like this as below... category is empty for me:
axios
.get('https://.............json')
.then((res) => {
this.setState({
myData: res.data,
error: res.error || null,
loading: false,
});
console.log('inside .then----' + JSON.stringify(this.state.myData));
});
const { navigation, route } = this.props;
const tabId = route.params?.tabId;
const tmpCategories = tabId
? this.state.myData[tabId]
: this.state.myData.victoria_bc;
this.setState({ categories: tmpCategories });
//console.log(route.params?.tabId);
Final code that is working for me..
export default class Categories extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
myData: [],
error: null,
};
}
componentDidMount() {
this.renderCategories();
}
renderCategories = () => {
axios
.get('https://.............json')
.then((res) => {
this.setState({
myData: res.data,
error: res.error || null,
loading: false,
});
//console.log('inside .then----' + JSON.stringify(this.state.myData));
});
};
render() {
if (this.state.loading) {
return (
<View
style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}
>
<ActivityIndicator />
</View>
);
} else {
const { navigation, route } = this.props;
const tabId = route.params?.tabId;
const categories = tabId
? this.state.myData[tabId]
: this.state.myData.victoria_bc;
//console.log(route.params?.tabId);
return (
<Block flex center style={styles.categories}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.categoryList}
>
<Block flex>
{categories.map((category) => (
<TouchableWithoutFeedback
key={`category-${category.id}`}
onPress={() =>
navigation.navigate('Category', { ...category })
}
>
<Block flex card style={[styles.category, styles.shadow]}>
<ImageBackground
source={{ uri: category.image }}
style={[
styles.imageBlock,
{ width: width - theme.SIZES.BASE * 2, height: 252 },
]}
imageStyle={{
width: width - theme.SIZES.BASE * 2,
height: 252,
}}
>
<Block style={styles.categoryTitle}>
<Text size={18} bold color={theme.COLORS.WHITE}>
{category.title}
</Text>
</Block>
</ImageBackground>
</Block>
</TouchableWithoutFeedback>
))}
</Block>
</ScrollView>
</Block>
);
}
}
}
export default class Categories extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
myData: [],
error: null,
categories: []
};
}
componentDidMount() {
renderCategories();
}
renderCategories = () => {
this.setState({ loading: true });
axios
.get('https://..............json')
.then((res) => {
this.setState({ myData: res.data,
error: res.error || null,
loading: false
});
const categoryLive = this.state.myData;
console.log(JSON.stringify(categoryLive));
});
};
render() {
// Set params in your render method :
const { navigation, route } = this.props;
const tabId = route.params?.tabId;
if (this.state.loading){
return (
<View style={{ flex : 1, alignItems: 'center', justifyContent: 'center' }}>
<ActivityIndicator/>
</View>
);
}
return (
// assign in your return statement
this.setState({ categories: tabId
? categoryLive[tabId]
: categoryLive.victoria_bc;})
//console.log(route.params?.tabId);
const { categories } = this.state.categories;
<Block flex center style={styles.categories}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.categoryList}
>
<Block flex>
{categories.map((category) => (
<TouchableWithoutFeedback
key={`category-${category.id}`}
onPress={() => navigation.navigate('Category', { ...category })}
>
<Block flex card style={[styles.category, styles.shadow]}>
<ImageBackground
source={{ uri: category.image }}
style={[
styles.imageBlock,
{ width: width - theme.SIZES.BASE * 2, height: 252 },
]}
imageStyle={{
width: width - theme.SIZES.BASE * 2,
height: 252,
}}
>
<Block style={styles.categoryTitle}>
<Text size={18} bold color={theme.COLORS.WHITE}>
{category.title}
</Text>
</Block>
</ImageBackground>
</Block>
</TouchableWithoutFeedback>
))}
</Block>
</ScrollView>
</Block>
);
}
}

Passing data from one component to another in React Native

I am setting Sub Domain URL's for single app. Sub domain name will enter at the first time. it saves to the async storage and need to retrieve it from a common component
Using the const, it's not working properly.
Here is the partially completed code. baseURL and socketURL is needed inside another component function. How can I access these constants from there ?
index_new.js
import * as React from 'react';
import { View } from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import Login from "../screens/common/login/login/login";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
sub_domain: '',
};
}
async getSchoolCode() {
let sub_domain = '';
try {
sub_domain = await AsyncStorage.getItem('SCHOOL_CODE') || ''
} catch (error) {
}
return sub_domain;
};
async setSubdomain() {
const sub_domain = await this.getschoolcode()
await this.setState({ sub_domain })
}
getBaseUrl() {
return `http://${this.state.sub_domain}.vidhyadhan.in:81/`;
}
getSocketIoUrl() {
return `http://${this.state.sub_domain}.vidhyadhan.in:8080/`;
}
async componentDidMount() {
await this.setSubdomain();
}
render() {
const baseUrl = this.getBaseUrl();
const socketIoUrl = this.getSocketIoUrl();
const extraProps = {
baseUrl,
socketIoUrl
}
return (
<View>
<Login {...extraProps} />
</View>
)
}
}
Login.js
import React, { Component } from 'react'
import {
Alert,
Keyboard,
Text,
View,
TextInput,
TouchableHighlight,
Image,
ActivityIndicator,
StatusBar,
} from 'react-native'
import config from "../../../../config";
import styles from './style'
import { Icon } from "react-native-elements";
import Toaster from '../../../../components/toaster'
import AsyncStorage from '#react-native-community/async-storage';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
credentials: {
schoolcode: "",
email: "",
password: "",
},
loading: false,
school_code: '',
};
}
async getschoolcode() {
let school_code = '';
try {
school_code = await AsyncStorage.getItem('SCHOOL_CODE') || ''
} catch (error) {
}
return school_code;
};
updateText(text, field) {
let newCredentials = Object.assign(this.state.credentials);
newCredentials[field] = text;
// setState should be done like this
this.setState({
credentials: newCredentials
})
if(field == 'schoolcode'){
AsyncStorage.setItem('SCHOOL_CODE', text);
this.getschoolcode().then((keyValue) => {
this.state.school_code = keyValue;
console.log(this.state.school_code);
});
}
}
async login() {
Keyboard.dismiss();
let credentials = this.state.credentials;
if (this.state.credentials.schoolcode == '' || this.state.credentials.email == '' || this.state.credentials.password == '') {
Toaster.toast('Please Enter a valid UserName and Password', '#d30000')
} else {
const that = this;
credentials.email = that.state.credentials.email;
this.setState({ loading: !this.state.loading });
const new_url = this.props.baseUrl;
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 => {
if (responseJson.confirmation === "success") {
AsyncStorage.setItem('USER_ID', responseJson.data.user_id.toString());
this.setState({ loading: !this.state.loading });
setTimeout(() => {
this.props.navigation.navigate("Home")
}, 500);
} else {
this.setState({ loading: !this.state.loading });
setTimeout(() => {
Toaster.toast('Please Enter a valid UserName and Password', '#d30000')
// 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')) {
Toaster.toast('Please check your internet connection or try again later', '#d30000')
}
}, 500);
})
}
}
render() {
const loginText = (this.state.loading) ? 'Loading' : 'Login';
return (
<View style={styles.container}>
<StatusBar backgroundColor="#2383c9"
translucent={true}
hidden={false}/>
<Image source={require('../../../../assets/images/icons/logo.png')}
style={{ width: 99, height: 99, margin: 5, }} />
<Text style={{ fontSize: 20, margin: 20, color: "#ffffff" }}>Vidhyadhan</Text>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon}
source={require('../../../../assets/images/icons/username.png')} />
<TextInput style={styles.inputs}
placeholder="School-Code"
underlineColorAndroid='transparent'
onChangeText={text => {
this.updateText(text, 'schoolcode')
}} value={this.state.schoolcode}
autoCorrect={false}
autoCapitalize={"none"}
/>
</View>
<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;
First, You're not setting the state correctly. Then, you're trying to set the state twice.
Here's a better way of doing it:
import * as React from 'react';
import { View } from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
sub_domain: '',
};
}
async getSchoolCode() {
let sub_domain = '';
try {
sub_domain = await AsyncStorage.getItem('sub_domain') || ''
} catch (error) {
}
return sub_domain;
};
async setSubdomain() {
const sub_domain = await this.getschoolcode()
await this.setState({ sub_domain })
}
getBaseUrl() {
return `http://${this.state.sub_domain}.vidhyadhan.in:81/`;
}
getSocketIoUrl() {
return `http://${this.state.sub_domain}.vidhyadhan.in:8080/`;
}
async componentDidMount() {
await this.setSubdomain();
}
render() {
const baseUrl = this.getBaseUrl();
const socketIoUrl = this.getSocketIoUrl();
return (
<View/>
);
}
}
Based on the comments, here's how your render can be:
render() {
const baseUrl = this.getBaseUrl();
const socketIoUrl = this.getSocketIoUrl();
const extraProps = {
baseUrl,
socketIoUrl
}
return (
<View>
<MyFirstComponent {...extraProps} />
<MySecondComponent {...extraProps} />
</View>
)
}
And in your MyFirstComponent, you can either use this.props.baseUrl or this.props.socketIoUrl