I have a Modal that displays a list of contacts. onPress, contacts are dynamically added to a View.
If a contact has already been added, on second onPress I would like to remove it from the View. For that I'm amending the state/array containing the contacts, using splice but it removes all the contacts at once.
I'm also trying to update the state of the 'Add' icon. If a contact has been added the Add icon Image should become the active one.
Not sure what I'm doing wrong?
Here's the Modal opened up:
My code:
import React, {Component} from 'react'
import {
Text,
View,
ListView,
ScrollView,
StyleSheet,
Image,
TouchableHighlight,
TextInput,
Modal,
} from 'react-native'
const friends = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
}).cloneWithRows([
{
id: 1,
firstname: 'name1',
surname: 'surname1',
image: require('../images/friends/avatar-friend-01.png')
},
{
id: 2,
firstname: 'name2',
surname: 'surname2',
image: require('../images/friends/avatar-friend-02.png')
},
{
id: 3,
firstname: 'name3',
surname: 'surname3',
image: require('../images/friends/avatar-friend-03.png')
},
])
class AppView extends Component {
state = {
isModalVisible: false,
contactsPicked: [],
friendsState: {},
}
setModalVisible = visible => {
this.setState({isModalVisible: visible})
}
pickContact = (friend) => {
if(this.state.contactsPicked.indexOf(friend) < 0){
var tempFriendsState = this.state.friendsState
tempFriendsState[friend.id] = true
this.setState({
contactsPicked: [ ...this.state.contactsPicked, friend],
friendsState: tempFriendsState,
})
}
else{
let index = this.state.contactsPicked.indexOf(friend)
let nextContacts = this.state.contactsPicked
nextContacts.splice(index,1)
let tempFriendsState = this.state.friendsState
tempFriendsState[friend.id] = false
this.setState({
contactsPicked: nextContacts,
friendsState: tempFriendsState,
})
}
}
removeContact = (friend) => {
let index = this.state.contactsPicked.indexOf(friend)
let nextContacts = this.state.contactsPicked
nextContacts.splice(index,1)
this.setState({
contactsPicked: nextContacts,
})
}
_renderAddFriendTile = () => {
return(
<View style={[styles.step, styles.stepThree]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Friend tile</Text>
</View>
{this.state.contactsPicked.length > 0 && (
<TouchableHighlight onPress={() => {this.removeContact(this.state.contactsPicked)}}>
<View>
{this.state.contactsPicked.map((contact,index) => (
<View key={index} style={[styles.row, styles.friendRow]}>
<Image source={contact.image} style={styles.friendIcon}></Image>
<Text style={styles.name}>{contact.firstname} </Text>
<Text style={styles.name}>{contact.surname}</Text>
<View style={styles.roundIconContainer}>
<View style={styles.roundIcon}>
<View style={[styles.removeButton, styles.buttonSmall]}>
<Image source={require('../images/button-cross-small.png')} style={styles.crossIconSmall}></Image>
</View>
</View>
</View>
</View>
))}
</View>
</TouchableHighlight>
)}
<TouchableHighlight style={styles.addFriendButtonContainer} onPress={() => {this.setModalVisible(true)}}>
<View style={styles.addFriendButton}>
<Text style={styles.addFriendButtonText}>Add friends</Text>
</View>
</TouchableHighlight>
</View>
)
}
render(){
return (
<ScrollView style={styles.container}>
<Modal
animationType={'fade'}
transparent={true}
visible={this.state.isModalVisible}
>
<View style={styles.addFriendModalContainer}>
<View style={styles.addFriendModal}>
<TouchableHighlight onPress={() => {this.setModalVisible(false)}}>
<View>
<Text>Close</Text>
</View>
</TouchableHighlight>
<ListView
dataSource={friends}
renderRow={(friend) => {
return (
<FriendRow
friend={friend}
pickContact={this.pickContact}
isSelected={this.state.friendsState[friend.id]}
/>
)
}}
/>
</View>
</View>
</Modal>
{this._renderAddFriendTile()}
</ScrollView>
)
}
}
class FriendRow extends Component {
render(){
return(
<TouchableHighlight onPress={() => {this.props.pickContact(this.props.friend)}}>
<View style={[styles.row, styles.friendRow]}>
<Image source={this.props.friend.image} style={styles.friendIcon}></Image>
<Text style={styles.name}>{this.props.friend.firstname} </Text>
<Text style={styles.name}>{this.props.friend.surname}</Text>
<View style={styles.roundIconContainer}>
<View style={styles.roundIcon}>
<View style={this.props.isSelected ? [styles.buttonActive, styles.buttonSmall]: [styles.modalButtonInactive, styles.buttonSmall]}>
<Image source={this.props.isSelected && require('../images/button-tick-small-on.png')} style={styles.buttonTickSmall}></Image>
</View>
</View>
</View>
</View>
</TouchableHighlight>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#e1e1e1'
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
step: {
backgroundColor: '#ffffff',
borderRadius: 4,
borderLeftWidth: 5,
flex: 1,
marginLeft: 10,
marginRight: 10,
marginBottom: 10,
paddingLeft: 15,
paddingRight: 10,
paddingTop: 15,
paddingBottom: 20,
shadowOffset: {
width: 0,
height: 2,
},
shadowRadius: 2,
shadowOpacity: 0.2,
shadowColor: '#000000',
},
stepThree: {
borderLeftColor: '#ffbd18',
},
heading: {
textAlign: 'center',
fontWeight: 'bold',
fontSize: 15,
color: '#333333',
},
addFriendButtonContainer: {
marginTop:15,
flex:1,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
addFriendButton: {
backgroundColor: '#ffbd18',
width: 270,
borderRadius: 4,
paddingTop: 15,
paddingBottom: 15,
},
addFriendButtonText: {
color: '#ffffff',
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
pickContainer: {
flex:1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
borderRightWidth: 1,
},
pickWrapper: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
marginTop: 10,
},
buttonBig: {
height: 60,
width: 60,
borderRadius: 30,
},
buttonSmall: {
height: 20,
width: 20,
borderRadius: 10,
},
buttonActive: {
backgroundColor: '#fd6769',
alignItems: 'center',
justifyContent: 'center',
},
buttonInactive: {
backgroundColor: '#eeeeee',
alignItems: 'center',
justifyContent: 'center',
},
removeButton:{
backgroundColor: '#cccbcb',
alignItems: 'center',
justifyContent: 'center',
},
modalButtonInactive: {
backgroundColor: '#ffffff',
borderWidth: 1,
borderColor: '#eeeeee',
},
buttonTickBig: {
width: 34,
height: 28,
},
buttonTickMinusBig: {
width: 18,
height: 8,
},
buttonTickSmall: {
width: 12,
height: 10,
},
crossIconSmall: {
width: 12,
height: 10,
},
pickText: {
color: '#c7c7c7',
fontWeight: 'bold',
},
addFriendModalContainer: {
flex: 1,
},
addFriendModal: {
flex: 1,
backgroundColor: '#ffffff',
borderRadius: 4,
paddingLeft: 15,
paddingRight: 10,
paddingTop: 20,
paddingBottom: 20,
shadowOffset: {
width: 0,
height: 2,
},
shadowRadius: 2,
shadowOpacity: 0.2,
shadowColor: '#000000',
textAlign: 'center',
},
nextButtonContainer: {
marginBottom: 20,
},
nextButton: {
textAlign:'right',
},
friendRow: {
height: 60,
borderBottomWidth: 1,
borderBottomColor: '#eeeeee',
justifyContent: 'flex-start',
},
friendIcon: {
width: 50,
height: 50,
marginRight: 25,
},
roundIconContainer:{
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'flex-end',
},
roundIcon: {
height: 20,
width: 20,
borderRadius: 10,
backgroundColor: '#fd6769',
justifyContent: 'center',
alignItems: 'center',
marginRight: 20,
},
})
export default AppView
'using splice but it removes all the contacts at once.'
Because you're using splice method wrong. Check the parameters the method gets.
http://www.w3schools.com/jsref/jsref_splice.asp
[ ...this.state.contactsPicked, this.state.contactsPicked.splice(friend)]
this doesn't work as you expected as well. It merges two arrays.
var parts = ['shoulders', 'knees'];
var parts2 = ['shoulders'];
var lyrics = [ ...parts, ...parts2 ];
console.log(lyrics)
It seems you don't have to use spread operator([...arr,.arr2]),
you can simply do that
Since it re creates subs every time modal's visiblity changes and even if you change state of parent component's state it does not re render subs so you need to keep internal state for you sub components
Also your _renderAddFriendTile method was working wrong too. When
you take a look at it carefully you will realize your mistake.
Don't forget to change your icons with my test icons
class AppView extends Component {
constructor(props) {
super(props);
this.state = {
isModalVisible: false,
contactsPicked: [],
friendsState: {},
}
}
setModalVisible = visible => {
this.setState({isModalVisible: visible})
}
pickContact = (friend) => {
if(this.state.contactsPicked.indexOf(friend) < 0){
var tempFriendsState = this.state.friendsState
tempFriendsState[friend.id] = true
this.setState({
contactsPicked: [ ...this.state.contactsPicked, friend],
friendsState: tempFriendsState,
})
}
else{
let index = this.state.contactsPicked.indexOf(friend)
let nextContacts = this.state.contactsPicked
nextContacts.splice(index,1)
let tempFriendsState = this.state.friendsState
tempFriendsState[friend.id] = false
this.setState({
contactsPicked: nextContacts,
friendsState: tempFriendsState,
})
}
}
removeContact = (friend) => {
let index = this.state.contactsPicked.indexOf(friend)
let nextContacts = this.state.contactsPicked
let tempFriendsState = this.state.friendsState
tempFriendsState[friend.id] = false
nextContacts.splice(index,1)
console.log('removeContact'+friend.id);
this.setState({
contactsPicked: nextContacts,
friendsState: tempFriendsState,
})
}
_renderAddFriendTile = () => {
return(
<View style={[styles.step, styles.stepThree]}>
<View style={{flex:1}}>
<Text style={styles.heading}>Friend tile</Text>
</View>
{ (this.state.contactsPicked.length) > 0 ?
this.state.contactsPicked.map((contact,index) => (
<TouchableHighlight onPress={() => {this.removeContact(contact)}}>
<View>
<View key={index} style={[styles.row, styles.friendRow]}>
<Image source={contact.image} style={styles.friendIcon}></Image>
<Text style={styles.name}>{contact.firstname} </Text>
<Text style={styles.name}>{contact.surname}</Text>
<View style={styles.roundIconContainer}>
<View style={styles.roundIcon}>
<View style={[styles.removeButton, styles.buttonSmall]}>
<Image source={require('./images/redtree.jpg')} style={styles.crossIconSmall}></Image>
</View>
</View>
</View>
</View>
</View>
</TouchableHighlight>
))
: null
}
<TouchableHighlight style={styles.addFriendButtonContainer} onPress={() => {this.setModalVisible(true)}}>
<View style={styles.addFriendButton}>
<Text style={styles.addFriendButtonText}>Add friends</Text>
</View>
</TouchableHighlight>
</View>
)
}
render(){
return (
<ScrollView style={styles.container}>
<Modal
animationType={'fade'}
transparent={true}
visible={this.state.isModalVisible}
>
<View style={styles.addFriendModalContainer}>
<View style={styles.addFriendModal}>
<TouchableHighlight onPress={() => {this.setModalVisible(false)}}>
<View>
<Text>Close</Text>
</View>
</TouchableHighlight>
<ListView
dataSource={friends}
renderRow={(friend) => {
return (
<FriendRow
friend={friend}
pickContact={this.pickContact}
isSelected={this.state.friendsState[friend.id]}
/>
)
}}
/>
</View>
</View>
</Modal>
{this._renderAddFriendTile()}
</ScrollView>
)
}
}
class FriendRow extends Component {
constructor(props) {
super(props);
this.state = {
isSelected:this.props.isSelected,
}
}
componentDidMount(){
console.log('didmount');
}
render(){
var imageSource = (this.state.isSelected==true) ? require('./images/tree.jpg') : ''
console.log('friend'+!this.props.isSelected)
return(
<TouchableHighlight onPress={() => {this.props.pickContact(this.props.friend);this.setState({isSelected:!this.state.isSelected})}}>
<View style={[styles.row, styles.friendRow]}>
<Image source={this.props.friend.image} style={styles.friendIcon}></Image>
<Text style={styles.name}>{this.props.friend.firstname} </Text>
<Text style={styles.name}>{this.props.friend.surname}</Text>
<View style={styles.roundIconContainer}>
<View style={styles.roundIcon}>
<View style={this.state.isSelected ? [styles.buttonActive, styles.buttonSmall]: [styles.modalButtonInactive, styles.buttonSmall]}>
<Image source={imageSource} style={styles.buttonTickSmall}></Image>
</View>
</View>
</View>
</View>
</TouchableHighlight>
)
}
}
You can use filter method to filter out contacts if it's already there in view.
To remove contacts from view if already added:
this.setState({
...state,
contactsPicked: this.state.contactsPicked.filter((contactsPicked,index)=> index != pickedContactsIndex)
})
Related
I need to make a screen like you see below in React Native
like that
I need to list this screen with this datalist I have
let denemeData = [
{
id: 1,
BestSellers: [
{
id: 1,
SellerName: 'Steril Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1254788325/photo/forget-sweet-try-home-sanitised-home.jpg?s=612x612&w=0&k=20&c=q6t80qrWvnWRln4PoxF8giI0hr9cNqdvFQiooFqIK3M=',
},
{
id: 2,
SellerName: 'Işıltı Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1218727916/photo/woman-wearing-gloves-cleaning-desktop.jpg?s=612x612&w=0&k=20&c=i0DvmRBBjo-Q4DaJHywi4mQzRYOCRjPKh3m7wIYHHNw=',
},
{
id: 3,
SellerName: 'Aybars Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1358089804/photo/beautiful-smiling-young-woman-cleaning-and-wiping-window-with-spray-bottle-and-rag-stock-photo.jpg?s=612x612&w=0&k=20&c=1OCBbZeIxBHAsrm6K7FTXgST91xb9TCaHYc74y1bq8s=',
},
{
id: 4,
SellerName: 'Hizmet Kolay',
imageUrl:
'https://media.gettyimages.com/id/1055221704/photo/young-woman-washing-window.jpg?s=612x612&w=0&k=20&c=Nd2TDn8pTRPe_bEkGec7ICNQ3pcoksMQWTCcGRVpfQI=',
},
{
id: 5,
SellerName: 'Aybars Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1358089804/photo/beautiful-smiling-young-woman-cleaning-and-wiping-window-with-spray-bottle-and-rag-stock-photo.jpg?s=612x612&w=0&k=20&c=1OCBbZeIxBHAsrm6K7FTXgST91xb9TCaHYc74y1bq8s=',
},
{
id: 6,
SellerName: 'Hizmet Kolay',
imageUrl:
'https://media.gettyimages.com/id/1055221704/photo/young-woman-washing-window.jpg?s=612x612&w=0&k=20&c=Nd2TDn8pTRPe_bEkGec7ICNQ3pcoksMQWTCcGRVpfQI=',
},
],
},
];`
I couldn't figure out how to list with FlatList as in the image because as it can be seen in the image, I need to make the first data large, the second and third data small and side by side, I tried to play with numColumns, I tried to play with numColumns, I tried to adjust the View manually, I couldn't do it in any way and my brain stopped, please guide me, I'm very tired and I can't do it, my brain stopped.
Thanks for ur helps
I tried giving numColumns value with FlatList, but I did not get the result I expected.;
<FlatList
bounces={false}
numColumns={2}
scrollEnabled={true}
data={sellers}
renderItem={({item}) => (
<Pressable
onPress={() => {
denemeFunc(item);
}}
style={{
height: 170,
width: '47%',
borderRadius: 10,
backgroundColor: 'red',
margin: 5,
}}>
<Image
style={{
height: '100%',
resizeMode: 'cover',
width: '100%',
borderRadius: 10,
position: 'absolute',
}}
source={{
uri: item.imageUrl,
}}
/>
<View
style={{
padding: 8,
justifyContent: 'flex-end',
alignItems: 'center',
height: '100%',
position: 'absolute',
}}>
<Text
style={{
color: 'white',
fontSize: 16,
fontFamily: 'Poppins-Bold',
textAlign: 'center',
}}>
{item.SellerName}
</Text>
</View>
</Pressable>
)}
showsVerticalScrollIndicator={false}
/>
as I can see in your layout, for the even lines you want a component with just one line and for odd lines you want a component with two images. So you can render different components according to the index of the list.
I think you can do something like this:
<FlatList
bounces={false}
numColumns={2}
scrollEnabled={true}
data={sellers}
renderItem={({item, index}) => (
if(index% 2 === 0){
// You render a component with just one line.
} else {
// You create the component with columns - A component with a
//flexDirection: 'row'...
}
)}
showsVerticalScrollIndicator={false}
/>
Hope this answer helps you :).
Use VirtualizedList for more flexibility and render items by row. Here is the simplified version.
Calculate row count based on the layout
Return array of items for a certain row based on the layout
Render items for the row
Optional: Add padding to the last item to compensate the partial row
const isOdd = (index) => index % 2 !== 0
// 1.
const getRowCount = (items) => items.length - Math.floor(items.length / 3)
// 2.
const getRow = (items, index) =>
isOdd(index)
? items.slice(index + (index / 2), index + (index / 2) + 2)
: [items[2 * index - index / 2]]
const requiresPadding = (items, index, row) =>
row.length == 1 && getRowCount(items) - 1 === index && isOdd(index)
...
<VirtualizedList
data={items}
getItemCount={getRowCount}
getItem={getRow}
renderItem={({ item: row, index }) => (
<View style={{ flexDirection: 'row' }}>
// 3.
{row.map((i) => <Item title={i.title}/>)}
// 4.
{requiresPadding(items, index, row) && <PaddingItem/>}
</View>
)}
keyExtractor={(row) => row[0].id}
/>
...
const Item = ({ title }) => (
<View style={{
flex: 1,
backgroundColor: '#eee',
height: 150,
justifyContent: 'center',
alignItems: 'center',
margin: 8,
}}>
<Text>{title}</Text>
</View>
);
const PaddingItem = () => (
<View style={{flex: 1, margin: 8}}/>
)
may be this will help you!
App.js
import React from 'react';
import {
SafeAreaView,
View,
FlatList,
StyleSheet,
ImageBackground,
Text,
StatusBar,
} from 'react-native';
const DATA = [
{
id: 1,
SellerName: 'Steril Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1254788325/photo/forget-sweet-try-home-sanitised-home.jpg?s=612x612&w=0&k=20&c=q6t80qrWvnWRln4PoxF8giI0hr9cNqdvFQiooFqIK3M=',
},
{
id: 2,
SellerName: 'Işıltı Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1218727916/photo/woman-wearing-gloves-cleaning-desktop.jpg?s=612x612&w=0&k=20&c=i0DvmRBBjo-Q4DaJHywi4mQzRYOCRjPKh3m7wIYHHNw=',
},
{
id: 3,
SellerName: 'Aybars Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1358089804/photo/beautiful-smiling-young-woman-cleaning-and-wiping-window-with-spray-bottle-and-rag-stock-photo.jpg?s=612x612&w=0&k=20&c=1OCBbZeIxBHAsrm6K7FTXgST91xb9TCaHYc74y1bq8s=',
},
{
id: 4,
SellerName: 'Hizmet Kolay',
imageUrl:
'https://media.gettyimages.com/id/1055221704/photo/young-woman-washing-window.jpg?s=612x612&w=0&k=20&c=Nd2TDn8pTRPe_bEkGec7ICNQ3pcoksMQWTCcGRVpfQI=',
},
{
id: 5,
SellerName: 'Aybars Temizlik',
imageUrl:
'https://media.gettyimages.com/id/1358089804/photo/beautiful-smiling-young-woman-cleaning-and-wiping-window-with-spray-bottle-and-rag-stock-photo.jpg?s=612x612&w=0&k=20&c=1OCBbZeIxBHAsrm6K7FTXgST91xb9TCaHYc74y1bq8s=',
},
{
id: 6,
SellerName: 'Hizmet Kolay',
imageUrl:
'https://media.gettyimages.com/id/1055221704/photo/young-woman-washing-window.jpg?s=612x612&w=0&k=20&c=Nd2TDn8pTRPe_bEkGec7ICNQ3pcoksMQWTCcGRVpfQI=',
},
];
const renderItem = ({ item }) => (
<>
<View>
{item.id == 1 && (
<View
style={{
margin: 10,
height: 120,
}}>
<ImageBackground
source={item.imageUrl}
style={{ width: '100%', height: '100%', borderRadius: 20 }}>
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
)}
{item.id == 2 ? (
<>
<View
style={{
flexDirection: 'row',
margin: 10,
height: 120,
width: 100,
justifyContent: 'space-between',
}}>
<View>
<ImageBackground
source={item.imageUrl}
style={{ width:150, height: '100%', borderRadius: 20 ,margin:5}}>
<Text
style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
<View>
<ImageBackground
source={item.imageUrl}
style={{ width:150, height: '100%', borderRadius: 20 ,margin:5}}>
<Text
style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
</View>
</>
) : null}
{item.id == 3 && (
<View
style={{
margin: 10,
height: 120,
}}>
<ImageBackground
source={item.imageUrl}
style={{ width: '100%', height: '100%', borderRadius: 20 }}>
<Text style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
)}
{item.id == 4 ? (
<>
<View
style={{
flexDirection: 'row',
margin: 10,
height: 120,
width: 100,
justifyContent: 'space-between',
}}>
<View>
<ImageBackground
source={item.imageUrl}
style={{ width:150, height: '100%', borderRadius: 20 ,margin:5}}>
<Text
style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
<View>
<ImageBackground
source={item.imageUrl}
style={{ width:150, height: '100%', borderRadius: 20 ,margin:5}}>
<Text
style={{ color: '#fff', fontSize: 20, fontWeight: 'bold' }}>
{item.SellerName}
</Text>
</ImageBackground>
</View>
</View>
</>
) : null}
</View>
</>
);
const App = () => {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
});
export default App;
here is output:
Please Help.In react native expo. I am using react-native-gesture-handler Swipeable the problem is I am not getting it how to add the update status API here . once I swipe it to collect samples it should be stay constant to samples collected. I have used redux i put all my codes below
in my actions here I put the API URL
export const updateStatus = (collected) => {
return async (dispatch) => {
const token = await SecureStore.getItemAsync("userToken");
const url = `/update-status`;
var formdata = new FormData();
formdata.append("Booking_no", "");
formdata.append("action ", collected );
const response = await api
.post(url, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
return res;
})
.catch((error) => {
return error.response;
});
dispatch({
type: "UPDATE_STATUS",
payload: response,
});
};
};
in reducer
case "UPDATE_STATUS": {
if (action.payload.status === 200) {
let newState = {
...state,
updatestatus: true,
};
return newState;
} else {
let newState = {
...state,
updatestatus: false,
};
return newState;
}
}
in component
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
Image,
Linking,
ActivityIndicator,
ScrollView,
} from "react-native";
import MaterialCommunityIcons from "react-native-vector-icons/MaterialCommunityIcons";
import Swipeable from "react-native-gesture-handler/Swipeable";
import Sampleitems from "./Sampleitems";
import { fetchBookingDetails, updateStatus } from "../../../../../actions";
import { connect } from "react-redux";
import { TouchableHighlight } from "react-native-gesture-handler";
class Orderitems extends Component {
constructor(props) {
super(props);
this.state = {
showMe: true,
};
}
componentDidMount() {
this.props.fetchBookingDetails(this.props.route.params.booking_id);
setTimeout(() => {
this.setState({
showMe: false,
});
}, 3000);
}
render() {
const LeftSwipeActions = () => {
return (
<View style={[styles.container1, styles.horizontal]}>
{this.state.showMe ? (
<View style={{ alignSelf: "center" }}>
<ActivityIndicator size="large" color="#4DB2F8" />
</View>
) : (
<View style={styles.sampleMain}>
<Text style={styles.sample}>Samples Collected</Text>
</View>
)}
</View>
);
};
let bookingtest = this.props.bookinglist;
const items =
bookingtest && bookingtest.items && bookingtest.items.length > 0 ? (
bookingtest.items.map((booking_test) => {
return (
<Sampleitems
key={booking_test.id}
quantity={
booking_test && booking_test.test ? (
<View
style={{
borderRadius: 5,
borderWidth: 1,
borderColor: "#4D4D4D",
height: 30,
width: 30,
paddingTop: 5,
}}
>
<Text style={{ textAlign: "center", fontSize: 12 }}>
1 x
</Text>
</View>
) : null
}
test={
booking_test && booking_test.test ? (
booking_test.test.test_name
) : (
<View style={{ alignSelf: "center" }}>
<Text style={{ color: "#A1E1F3" }}>No Test Available</Text>
</View>
)
}
/>
);
})
) : (
<View style={{ alignSelf: "center" }}>
<Text style={{ color: "#A1E1F3" }}>No Test Available</Text>
</View>
);
const { navigation, family } = this.props;
let bookdata = this.props.family_data;
return (
<View style={styles.container} key={bookdata.id}>
<ScrollView>
<View style={{ margin: 15, marginBottom: 100, marginTop: 100 }}>
<View style={{ borderRadius: 10 }}>
<View style={{ padding: 20, backgroundColor: "white" }}>
<View
style={{ flex: 1, flexDirection: "row", paddingRight: 15 }}
>
<View
style={{
borderRadius: 5,
backgroundColor: "#4D4D4D",
height: 30,
width: 30,
paddingTop: 4,
}}
>
<Image
source={require("../../../../../assets/delivery/placeholder.png")}
resizeMode="contain"
tintColor="white"
style={{
height: 20,
width: 20,
alignSelf: "center",
}}
/>
</View>
<View style={{ paddingRight: 2, paddingLeft: 10 }}>
<Text style={{ fontWeight: "bold", color: "black" }}>
{bookdata && bookdata.family
? bookdata.family.name
: null}
</Text>
<Text style={{ fontSize: 12 }}>
{bookdata && bookdata.family
? bookdata.family.mobile
: null}
</Text>
<Text style={{ paddingBottom: 5, fontSize: 12 }}>
{bookdata && bookdata.family
? bookdata.family.adr_line_1
: null}
</Text>
<View style={{ flexDirection: "row" }}>
<TouchableHighlight
style={{ width: "130%" }}
underlayColor="transparent"
onPress={() => {
Linking.openURL(
`http://maps.google.com/?q=${
bookdata && bookdata.family
? bookdata.family.adr_line_1
: null
}`
);
}}
>
<View
style={{
backgroundColor: "#202877",
flexDirection: "row",
padding: 10,
paddingLeft: 0,
paddingRight: 0,
borderRadius: 7,
justifyContent: "center",
// width: "80%",
}}
>
<MaterialCommunityIcons
name="directions"
style={{ color: "white" }}
size={20}
/>
<Text
style={{
color: "white",
alignSelf: "center",
fontSize: 10,
paddingRight: 5,
}}
>
Get Direction
</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={{ width: "150%" }}
underlayColor="transparent"
onPress={() => {
Linking.openURL(
`tel:${
bookdata && bookdata.family
? bookdata.family.mobile
: null
}`
);
}}
>
<View
style={{
backgroundColor: "#202877",
flexDirection: "row",
padding: 10,
borderRadius: 7,
paddingLeft: 0,
paddingRight: 0,
justifyContent: "center",
marginLeft: 40,
}}
>
<MaterialCommunityIcons
name="cellphone"
style={{ color: "white" }}
size={20}
/>
<Text
style={{
color: "white",
alignSelf: "center",
fontSize: 10,
paddingRight: 5,
}}
>
Call Now
</Text>
</View>
</TouchableHighlight>
</View>
</View>
</View>
</View>
</View>
<View style={{ borderRadius: 10, marginTop: 30 }}>
<View
style={{
flex: 1,
flexDirection: "row",
padding: 20,
backgroundColor: "#FAFAFA",
borderTopLeftRadius: 10,
borderTopRightRadius: 10,
}}
>
<Image
source={require("../../../../../assets/delivery/menu.png")}
resizeMode="contain"
style={{
width: 15,
height: 15,
alignSelf: "center",
}}
/>
<Text style={{ fontSize: 17 }}> Sample Items </Text>
</View>
<View style={{ padding: 20, backgroundColor: "white" }}>
{items}
</View>
</View>
</View>
</ScrollView>
{/* header */}
<View
style={{
flex: 1,
top: 0,
right: 0,
left: 0,
paddingTop: 35,
paddingBottom: 10,
position: "absolute",
backgroundColor: "white",
shadowColor: "black",
shadowOffset: {
width: 0,
height: 12,
},
shadowOpacity: 1,
shadowRadius: 16.0,
elevation: 2,
}}
>
<View
style={{
flex: 1,
backgroundColor: "white",
padding: 10,
flexDirection: "row",
}}
>
<MaterialCommunityIcons
style={{ alignSelf: "center" }}
name="chevron-left"
size={26}
onPress={() => navigation.goBack(null)}
/>
<Text
style={{
fontSize: 17,
fontWeight: "800",
alignSelf: "center",
paddingLeft: 40,
}}
>
#{bookdata.booking_no}
</Text>
</View>
</View>
{/* footer */}
<View
style={{
flex: 1,
bottom: 0,
right: 0,
left: 0,
position: "absolute",
}}
>
<Swipeable renderLeftActions={LeftSwipeActions}>
<View style={styles.collectMainMain}>
<MaterialCommunityIcons
name="chevron-right"
style={styles.material}
size={20}
/>
<View style={styles.collectMain}>
<Text style={styles.collect}>Collect Samples</Text>
</View>
</View>
</Swipeable>
</View>
</View>
);
}
_onLoadEnd = () => {
this.setState({
loading: false,
});
};
}
const mapStateToProps = (state) => {
return {
family_data: state.detailData.booking_details,
bookinglist: state.detailData.booking_details,
update_status: state.detailData.updatestatus,
};
};
export default connect(mapStateToProps, {
fetchBookingDetails,
updateStatus,
})(Orderitems);```
Don't check the status code on your reducer. you can easily check it on your api.post and then send a proper action to the reducer:
const response = await api
.post(url, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((res) => {
return res.json();
})
.then(res => {
if(res.status === 200) {
dispatch({
type: "UPDATE_STATUS_SUCCESS",
})
} else {
dispatch({
type: "UPDATE_STATUS_FAILURE",
})
}
})
.catch((error) => {
console.log(error);
dispatch({
type: "UPDATE_STATUS_FAILURE",
})
});
Now, if the response status was 200, the proper action will be dispatched and if there is an error or the sample UPDATE_STATUS_FAILURE will be dispatched.
In the reducer:
// rest of the codes ...
case "UPDATE_STATUS_SUCCESS":
return{
...state,
updateStatus: true,
}
case "UPDATE_STATUS_FAILURE":
return{
...state,
updateStatus: false
}
// rest of the codes ...
I'm trying to make a toy stopwatch app in order to learn react-native.
I made a lap system, but it is getting way too slow when there are >15 laps. I think the poor performance point is the laps: this.state.laps.concat([d - this.state.lapTimerStart]) part, because of .concat is making a new object every time the Lap button is pressed.
I've heard that .push is way faster than .concat.
So I tried to use .push, but because .push was mutating the array, and FlatList was a PureComponent so it re-rendered only when the props have changed.
I found a way, but it was just the same as doing .concat because basically, it was
let lapArr = this.state.laps;
Array.prototype.push.apply(lapArr, [d - this.state.lapTimerStart]);
this.setState({
laps: lapArr,
})
The full code is
import React, {Component} from 'react';
import {
View,
Text,
StyleSheet,
TouchableHighlight,
FlatList,
} from 'react-native';
import {useTheme} from 'react-native-paper';
import TimeFormatter from 'minutes-seconds-milliseconds';
class Stopwatch extends Component {
constructor(props) {
super(props);
this.state = {
laps: [],
isRunning: false,
mainTimer: null,
lapTimer: null,
mainTimerStart: null,
lapTimerStart: null,
};
}
handleLapReset() {
let {isRunning, mainTimerStart, lapTimer} = this.state;
if (mainTimerStart) {
if (isRunning) {
const d = new Date();
this.setState({
lapTimerStart: d,
lapTimer: d - this.state.lapTimerStart + lapTimer,
laps: this.state.laps.concat([d - this.state.lapTimerStart]),
});
return;
}
this.state.laps = [];
this.setState({
mainTimerStart: null,
lapTimerStart: null,
mainTimer: 0,
lapTimer: 0,
});
}
}
handleStartStop() {
let {isRunning, mainTimer, lapTimer} = this.state;
if (isRunning) {
clearInterval(this.interval);
this.setState({
isRunning: false,
});
return;
}
const d = new Date();
this.setState({
mainTimerStart: d,
lapTimerStart: d,
isRunning: true,
});
this.interval = setInterval(() => {
const t = new Date();
this.setState({
mainTimer: t - this.state.mainTimerStart + mainTimer,
lapTimer: t - this.state.lapTimerStart + lapTimer,
});
}, 10);
}
_renderTimers() {
const {theme} = this.props;
return (
<View
style={[
styles.timerWrapper,
{backgroundColor: theme.colors.background},
]}>
<View style={styles.timerWrapperInner}>
<Text style={[styles.lapTimer, {color: theme.colors.text}]}>
{TimeFormatter(this.state.lapTimer)}
</Text>
<Text style={[styles.mainTimer, {color: theme.colors.text}]}>
{TimeFormatter(this.state.mainTimer)}
</Text>
</View>
</View>
);
}
_renderButtons() {
const {theme} = this.props;
return (
<View style={styles.buttonWrapper}>
<TouchableHighlight
underlayColor={theme.colors.disabled}
onPress={this.handleLapReset.bind(this)}
style={[styles.button, {backgroundColor: theme.colors.background}]}>
<Text style={[styles.lapResetBtn, {color: theme.colors.text}]}>
{this.state.mainTimerStart && !this.state.isRunning
? 'Reset'
: 'Lap'}
</Text>
</TouchableHighlight>
<TouchableHighlight
underlayColor={theme.colors.disabled}
onPress={this.handleStartStop.bind(this)}
style={[styles.button, {backgroundColor: theme.colors.background}]}>
<Text
style={[styles.startBtn, this.state.isRunning && styles.stopBtn]}>
{this.state.isRunning ? 'Stop' : 'Start'}
</Text>
</TouchableHighlight>
</View>
);
}
_renderLaps() {
return (
<View style={styles.lapsWrapper}>
<FlatList
data={this.state.laps}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
</View>
);
}
keyExtractor(item, index) {
return index.toString();
}
renderItem({item, index}) {
return (
<View style={styles.lapRow}>
<View style={styles.lapStyle}>
<View style={styles.lapBoxStyle} />
<Text style={styles.lapNumber}>{index + 1}</Text>
</View>
<View style={styles.lapStyle}>
<Text style={styles.lapTime}>{TimeFormatter(item)}</Text>
</View>
</View>
);
}
render() {
return (
<View style={styles.container}>
<View style={styles.top}>{this._renderTimers()}</View>
<View style={styles.middle}>{this._renderButtons()}</View>
<View style={styles.bottom}>{this._renderLaps()}</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {flex: 1},
timerWrapper: {
justifyContent: 'center',
flex: 1,
},
top: {
flex: 1,
},
middle: {
flex: 1,
backgroundColor: '#F0EFF5',
},
bottom: {
flex: 2,
},
mainTimer: {
fontSize: 50,
fontFamily: 'CircularStd-Medium',
alignSelf: 'center',
},
lapTimer: {
fontSize: 18,
fontFamily: 'CircularStd-Medium',
alignSelf: 'flex-end',
},
timerWrapperInner: {
alignSelf: 'center',
},
buttonWrapper: {
flexDirection: 'row',
justifyContent: 'space-around',
paddingTop: 15,
paddingBottom: 30,
},
button: {
height: 80,
width: 80,
borderRadius: 40,
backgroundColor: '#FFF',
justifyContent: 'center',
alignItems: 'center',
},
lapRow: {
flexDirection: 'row',
justifyContent: 'space-between',
height: 40,
paddingTop: 10,
},
lapNumber: {
flexDirection: 'row',
fontSize: 16,
fontFamily: 'CircularStd-Book',
color: '#777',
flex: 1,
},
lapTime: {
flexDirection: 'row',
color: '#000',
fontSize: 20,
fontFamily: 'CircularStd-Book',
flex: 1,
},
startBtn: {
color: '#0C0',
fontFamily: 'CircularStd-Book',
},
stopBtn: {
color: '#C00',
fontFamily: 'CircularStd-Book',
},
lapsWrapper: {
backgroundColor: '#ddd',
},
lapResetBtn: {
fontFamily: 'CircularStd-Book',
},
lapStyle: {
width: '40%',
flexDirection: 'row',
},
lapBoxStyle: {
flexDirection: 'row',
flex: 1,
},
});
export default function StopwatchScreen(props) {
const theme = useTheme();
return <Stopwatch {...props} theme={theme} />;
}
I tried not to use arrow functions, many news, but it didn't help that much.
FlatList is a pure component and it is mandatory to give new ref of data prop to render list . You should use concat but it created new object.
i think the main issue is renderItem.
create a separate PureComponent to avoid re-rendeing of items
class Item extends PureComponent {
const {item,index} = this.props;
return (
<View style={styles.lapRow}>
<View style={styles.lapStyle}>
<View style={styles.lapBoxStyle} />
<Text style={styles.lapNumber}>{index + 1}</Text>
</View>
<View style={styles.lapStyle}>
<Text style={styles.lapTime}>{TimeFormatter(item)}</Text>
</View>
</View>
);
}
and use in render item
renderItem({item, index}) {
return (
<Item item={item} index={index} />
);
}
How can I get the share icon on the same row as the text?
import React, {Component} from 'react';
import {
ActivityIndicator,
AsyncStorage,
Dimensions,
Image,
ScrollView,
Share,
StatusBar,
StyleSheet,
TouchableOpacity,
View
} from 'react-native';
import {Text} from 'react-native-elements';
import {Button} from 'react-native-share';
import Hyperlink from 'react-native-hyperlink'
import Icon from 'react-native-vector-icons/dist/FontAwesome';
const SCREEN_WIDTH = Dimensions.get('window').width;
const SCREEN_HEIGHT = Dimensions.get('window').height;
const IMAGE_SIZE = SCREEN_WIDTH - 80;
class CustomButton extends Component {
constructor() {
super();
this.state = {
selected: false
};
}
componentDidMount() {
const {selected} = this.props;
this.setState({
selected
});
}
render() {
const {title} = this.props;
const {selected} = this.state;
return (
<Button
title={title}
titleStyle={{fontSize: 15, color: 'white'}}
buttonStyle={selected ? {
backgroundColor: 'rgba(213, 100, 140, 1)',
borderRadius: 100,
width: 127
} : {
borderWidth: 1,
borderColor: 'white',
borderRadius: 30,
width: 127,
backgroundColor: 'transparent'
}}
containerStyle={{marginRight: 10}}
onPress={() => this.setState({selected: !selected})}
/>
);
}
}
class Fonts extends Component {
constructor(props) {
super(props);
this.state = {
...this.state,
selectedIndex: 0,
value: 0.5,
dataSource: null,
isLoading: true,
visible: false
};
this.componentDidMount = this.componentDidMount.bind(this);
}
getNavigationParams() {
return this.props.navigation.state.params || {}
}
componentDidMount() {
if (AsyncStorage.getItem('name')) {
this.setState({'name': AsyncStorage.getItem('name')});
}
return fetch('http://www.koolbusiness.com/newvi/' + this.props.navigation.state.params.id + '.json')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
...this.state,
isLoading: false,
dataSource: responseJson,
fontLoaded: true
}, function () {
});
})
.catch((error) => {
console.error(error);
});
}
onCancel() {
console.log("CANCEL")
this.setState({visible: false});
}
onOpen() {
console.log("OPEN")
this.setState({visible: true});
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
let shareOptions = {
message: 'http://www.koolbusiness.com/newvi/' + this.props.navigation.state.params.id + '.html',
url: 'http://bam.tech',
title: this.state.dataSource.title,
subject: this.state.dataSource.title // for email
};
return (
<View style={{flex: 1}}>
<StatusBar
barStyle="light-content"
/>
{this.state.fontLoaded ?
<View style={{flex: 1, backgroundColor: 'rgba(47,44,60,1)'}}>
<View style={styles.statusBar}/>
<View style={styles.navBar}><TouchableOpacity onPress={() => {
Share.share(shareOptions);
}}>
<View>
<Text> <Icon color="white" name="share-alt" size={42}/></Text>
</View>
</TouchableOpacity>
<Text style={styles.nameHeader}>
{this.state.dataSource.title}
</Text>
</View>
<ScrollView style={{flex: 1}}>
<View style={{justifyContent: 'center', alignItems: 'center'}}>
<Image
source={{uri: this.state.dataSource.img ? this.state.dataSource.img : "http://www.koolbusiness.com/_/images/icons/electronics_icon.png"}}
style={{width: IMAGE_SIZE, height: IMAGE_SIZE, borderRadius: 10}}
/>
</View>
<View style={{
flex: 1,
flexDirection: 'row',
marginTop: 20,
marginHorizontal: 40,
justifyContent: 'center',
alignItems: 'center'
}}>
<Text style={{flex: 1, fontSize: 26, color: 'white'}}>
{this.state.dataSource.title}
</Text>
</View>
<View style={{flex: 1, marginTop: 20, width: SCREEN_WIDTH - 80, marginLeft: 40}}>
<Text style={{flex: 1, fontSize: 15, color: 'white'}}>
{this.state.dataSource.date}
</Text>
<Hyperlink linkDefault={true}>
<Text style={{flex: 1, fontSize: 15, color: 'white'}} >
{this.state.dataSource.text}
</Text>
</Hyperlink>
</View>
</ScrollView>
</View> :
<Text>Loading...</Text>
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
}, nameHeader: {
color: 'white',
fontSize: 22,
textAlign: 'center'
},
textStyle: {
fontSize: 18,
padding: 10,
},
});
export default Fonts;
It works as expected but I want to render the share icon on the same row as the title text.
Can it be done?
You can use "flexDirection" to 'row' and group share icon along with the title in a view:
<View style={styles.navBar}>
<TouchableOpacity onPress={() => {Share.share(shareOptions); }}>
<View>
<Text>
<Icon color="white" name="share-alt" size={42}/>
</Text>
</View>
</TouchableOpacity>
<Text style={styles.nameHeader}>
{this.state.dataSource.title}
</Text>
</View>
add the below styling to your navBar className :
navBar: {
flex: 1,
flexDirection: 'row'
},
Also, you are using Text and a View in your TouchableOpacity which I think is not needed so I removed those and did a snack on expo similar to your code, please check it here :
https://snack.expo.io/Hk3lrAQ9f
I am learning react native for the first time for developing android app not IOS one and I was learning from Building a Simple ToDo App With React Native and Firebase tutorial from youtube.But I am getting an error while trying to add items. I get following error
Firebase.push failed: first argument contains an invalid key($$typeof) in property 'restaurant.restaurant_name.targetInst._nativeParent._currentElement'.keys must be non-empty strings and cant contain ".","#","$","/","["
What might be creating this issue?
import React, { Component } from 'react';
import Firebase from 'firebase';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight,
TextInput,
ListView
} from 'react-native';
class foodOrderSystem extends Component {
constructor(props){
super(props);
const firebaseRef = new Firebase('foodordersystem.firebaseio.com');
console.log(firebaseRef);
this.itemRef = firebaseRef.child('restaurant');
this.state = {
newRestaurant:'',
// estimated_delivery:'',
// description:'',
restaurantSource: new ListView.DataSource({rowHasChanged: (row1,row2) => row1 !== row2})
};
this.restaurant = [ ];
}
componentDidMount() {
this.itemRef.on('child_added', (snap) => {
this.restaurant.push({
id:snap.key(),
text:snap.val()
});
this.setState({
restaurantSource:this.state.restaurantSource.cloneWithRows(this.restaurant)
});
});
this.itemRef.on('child_removed', (snap) => {
this.restaurant = this.restaurant.filter((x) => x.id !== snap.key());
this.setState({
restaurantSource:this.state.restaurantSource.cloneWithRows(this.restaurant)
});
});
}
addRestaurant(){
if(this.state.newRestaurant !== ''){
this.itemRef.push({
restaurant_name: this.state.newRestaurant
});
this.setState({ newRestaurant:''});
}
}
removeRestaurant(rowData){
this.itemRef.child(rowData.id).remove();
}
render() {
return (
<View style={styles.appContainer}>
<View style={styles.titleView}>
<Text style={styles.titleText}>
foodOrderSystem
</Text>
</View>
<View style={styles.inputcontainer}>
<TextInput
style={styles.input}
onChange={(text) => this.setState({newRestaurant:text})}
value={this.state.newRestaurant} />
<TouchableHighlight
style={styles.button}
onPress={ () => this.addRestaurant() }
underlayColor="#00ffff">
<Text style={styles.btnText}>Add</Text>
</TouchableHighlight>
</View>
<ListView
dataSource={this.state.restaurantSource}
renderRow={this.renderRow.bind(this)} />
</View>
);
}
renderRow(rowData){
return(
<TouchableHighlight
underlayColor="#dddddd"
onPress={() => this.removeRestaurant(rowData)}>
<View>
<View style={styles.row}>
<Text style={styles.todoText}>{rowData.text}</Text>
</View>
<View style={styles.separator} />
</View>
</TouchableHighlight>
);
}
}
const styles = StyleSheet.create({
appContainer:{
flex: 1
},
titleView:{
backgroundColor: '#48afdb',
paddingTop: 30,
paddingBottom: 10,
flexDirection: 'row'
},
titleText:{
color: '#fff',
textAlign: 'center',
fontWeight: 'bold',
flex: 1,
fontSize: 20,
},
inputcontainer: {
marginTop: 5,
padding: 10,
flexDirection: 'row'
},
button: {
height: 36,
flex: 2,
flexDirection: 'row',
backgroundColor: '#48afdb',
justifyContent: 'center',
color: '#FFFFFF',
borderRadius: 4,
},
btnText: {
fontSize: 18,
color: '#fff',
marginTop: 6,
},
input: {
height: 36,
padding: 4,
marginRight: 5,
flex: 4,
fontSize: 18,
borderWidth: 1,
borderColor: '#48afdb',
borderRadius: 4,
color: '#48BBEC'
},
row: {
flexDirection: 'row',
padding: 12,
height: 44
},
separator: {
height: 1,
backgroundColor: '#CCCCCC',
},
todoText: {
flex: 1,
},
});
AppRegistry.registerComponent('foodOrderSystem', () => foodOrderSystem);
Here is the attachment of error