React Native - How to select multiple items and display them? - react-native

I would like to display selected items, but the situation I have got is not showing images but only the backgroundColor. There is image uri in productData, so I would like to display the uri. Another issue I am having is that the CheckBox is not checked.
My code below :
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 100,
},
topContainer: {
flexDirection: 'row',
marginHorizontal: 15,
paddingBottom: 20,
paddingTop: 10,
borderBottomWidth: 0.5,
borderColor: colors.very_light_pink,
},
iconWrap: {
width: 60,
height: 60,
borderRadius: 6,
backgroundColor: '#cccccc',
alignItems: 'center',
justifyContent: 'center',
marginRight: 5,
},
icon: {
width: 20,
height: 20,
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginHorizontal: 15,
marginBottom: 15,
},
});
const productData = [
{
id: 0,
productName: 'a',
price: 45000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/8211/407/250/73/w/563/8211407250_2_1_1.jpg?ts=1613387641299',
},
{
id: 1,
productName: 'b',
price: 45000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/0526/407/707/2/w/1280/0526407707_6_1_1.jpg?ts=1610451943259',
},
{
id: 2,
productName: 'c',
price: 129000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/0706/442/710/2/w/563/0706442710_2_1_1.jpg?ts=1614254205907',
},
{
id: 3,
productName: 'd',
price: 139000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/0706/431/446/2/w/563/0706431446_2_1_1.jpg?ts=1613386951068',
},
{
id: 4,
productName: 'e',
price: 189000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/4162/536/401/2/w/1280/4162536401_1_1_1.jpg?ts=1613122054256',
},
{
id: 5,
productName: 'f',
price: 89000,
image:
'https://static.zara.net/photos///2021/V/0/2/p/4165/537/430/2/w/563/4165537430_1_1_1.jpg?ts=1613122064808',
},
];
const LiveAddProducts = (props) => {
const [productClicked, setProductClicked] = useState(null);
const [selectedProducts, setSelectedProducts] = useState([]);
useEffect(() => {
if (productClicked !== null) {
setSelectedProducts((prevState) => [
...prevState,
// I believe this should be changed
{ id: prevState.length, image: productClicked },
]);
setProductClicked(null);
}
}, [productClicked]);
console.log(selectedProducts.image);
return (
<View style={[styles.container]}>
<View style={[styles.topContainer]}>
<TouchableOpacity style={[styles.iconWrap]}>
<Image source={assets.live_add_icon} style={[styles.icon]} />
</TouchableOpacity>
{selectedProducts.map((item, index) => (
<TouchableOpacity style={[styles.iconWrap]} key={item.id}>
<Image source={{ uri: productData.image }} style={[styles.icon]} />
</TouchableOpacity>
))}
</View>
<ScrollView style={{ paddingTop: 20 }}>
{productData.map((item, index) => (
<View style={[styles.row]}>
<ProductsList
price={item.price}
image={item.image}
productName={item.productName}
/>
// Any problems here?
<CheckBox
size={20}
onPress={() => setProductClicked(index)}
source={
productClicked === index
? assets.icon_check_on
: assets.checked_off
}
/>
</View>
))}
</ScrollView>
<BottomButton
btnText={'Add Items'}
buttonStyle={{ height: 50, backgroundColor: colors.iris }}
/>
</View>
);
};
LiveAddProducts.propTypes = {};
export default LiveAddProducts;
The image which has problems :

useEffect(() => {
if (productClicked !== null) {
setSelectedProducts((prevState) => [
...prevState,
// I believe this should be changed
{ id: prevState.length, image: productClicked },
]);
setProductClicked(null);
}
}, [productClicked]);
Here, you'd want to replace this with the index of the element
id: prevState.length
Also,
{selectedProducts.map((item, index) => (
<TouchableOpacity style={[styles.iconWrap]} key={item.id}>
<Image source={{ uri: productData.image }} style={[styles.icon]} />
</TouchableOpacity>
))}
Here, the uri should be item.image, as that is where you hold the data for your item when it is rendered in this loop

Related

React Native: How do I switch the state of only one item in FlatList?

what happens is the following fact: I want to add "switch/toggle" next to id 2.3 and 4 items, but it's getting on all items on the flatlist. I used "import SwitchSelector from "react-native-switch-selector"; " Can anyone who understands flatlist help me? I will be very happy and grateful
I'm not getting it at all, and I'm thinking of redoing my code because of this problem
Settings.js
import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image} from 'react-native';
import SwitchSelector from "react-native-switch-selector";
import React, {useState} from 'react'
const Settings = () => {
const [data, setdata] = useState(DATA);
const [isRender, setisRender] = useState(false);
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png')},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png')},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png')},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png')},
//{id: 5, text: 'Logout'},
]
const renderItem = ({item}) => {
return(
<TouchableOpacity style= {styles.item}>
<View style={ styles.avatarContainer }>
<Image source={ item.image } style={ styles.avatar } />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
//marginHorizontal: 21
},
item:{
borderBottomWidth: 1,
borderBottomColor: '#808080',
alignItems: 'flex-start',
flexDirection: 'row',
},
avatarContainer: {
backgroundColor: 'transparent',
//borderRadius: 100,
height: 30,
width: 30,
justifyContent: 'center',
alignItems: 'center'
},
avatar: {
height: 25,
width: 25,
bottom: -25,
marginLeft: 30
},
text:{
marginVertical: 30,
fontSize: 20,
fontWeight: 'bold',
marginLeft: 30,
marginBottom: 10,
bottom: 5
}
});
export default Settings;
Well here is my approach to your problem as much as I understood;
it also actively changes the values of data for further usage of App
const [data, setData] = useState([
{ id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), chosen: false },
{ id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), chosen: false },
{ id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), chosen: false },
{ id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), chosen: false },
//{id: 5, text: 'Logout'},
])
const [isRender, setisRender] = useState(false);
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.item}>
<View style={styles.avatarContainer}>
<Image source={item.image} style={styles.avatar} />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.id > 1 && <Switch
thumbColor={item.chosen == false ? "red" : "green"}
value={item.chosen}
onChange={() => setData(data.map(index =>
item.id === index.id
? {...index, chosen : !index.chosen}
: index
))}
/>}
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);};
You could try adding a boolean property to each item in DATA. You could then conditionally show a <SwitchSelector /> in renderItem based on that property.
For example, below I added the property showSwitch and used a ternary expression to conditionally show a <SwitchSelector /> in renderItem:
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), showSwitch: false},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), showSwitch: true},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), showSwitch: true},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), showSwitch: true},
//{id: 5, text: 'Logout'}
]
...
const renderItem = ({ item }) => {
return (
<TouchableOpacity style={styles.item}>
<View style={styles.avatarContainer}>
<Image source={item.image} style={styles.avatar} />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.showSwitch ? <SwitchSelector /> : null}
</TouchableOpacity>
);
};
This works from me:
import { SafeAreaView,Text, View, FlatList,
TouchableOpacity, StyleSheet, Image, Switch} from 'react-native';
import React, {useState, useEffect} from 'react';
import {TouchID} from 'react-native-touch-id';
const Settings = () => {
const [data, setdata] = useState(DATA);
const [isRender, setisRender] = useState(false);
const DATA = [
{id: 1, text: 'Perfil', image: require('../../assets/images/user.png'), switch: false},
{id: 2, text: 'Dark/Light mode', image: require('../../assets/images/light-up.png'), switch: true},
{id: 3, text: 'TouchId', image: require('../../assets/images/fingerprint.png'), switch: true},
{id: 4, text: 'Notificações', image: require('../../assets/images/bell-fill.png'), switch: true},
//{id: 5, text: 'Logout'}
]
const renderItem = ({item}) => {
return(
<TouchableOpacity
style= {styles.item}
>
<View style={ styles.avatarContainer }>
<Image source={ item.image } style={ styles.avatar } />
</View>
<View>
<Text style={styles.text}>{item.text}</Text>
</View>
{item.switch ? <Switch /> : null}
</TouchableOpacity>
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
keyExtractor={(item) => item.id.toString()}
renderItem={renderItem}
extraData={isRender}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 20
//marginHorizontal: 21
},
item:{
borderBottomWidth: 1,
borderBottomColor: '#808080',
alignItems: 'flex-start',
flexDirection: 'row',
},
avatarContainer: {
backgroundColor: 'transparent',
//borderRadius: 100,
height: 30,
width: 30,
justifyContent: 'center',
alignItems: 'center',
},
avatar: {
height: 25,
width: 25,
bottom: -25,
marginLeft: 30
},
text:{
marginVertical: 30,
fontSize: 20,
fontWeight: 'bold',
marginLeft: 30,
marginBottom: 10,
bottom: 5
},
});
export default Settings;

Add to cart in react native

I am creating my first professional react native app for a new start up, I like to do so.
This is based om a Product delarship.
Since I am not able to Pass the checked products to the Cart Page. Please Help me to do future.
I just created it in expo for react-native
Please Help me
Please Help I am stuck here.
import React from "react";
import styled from "styled-components";
import { Dimensions } from "react-native";
import { StatusBar } from "expo-status-bar";
import MedCard from "../components/MidCard";
import ProductName from "../components/Prices";
import Price from "../components/Prices";
import { LinearGradient } from "expo-linear-gradient";
import {
StyleSheet,
Button,
Text,
View,
TouchableOpacity,
ScrollView,
Image,
ActivityIndicator,
TextInput,
Alert,
} from "react-native";
import {
MaterialIcons,
AntDesign,
Ionicons,
MaterialCommunityIcons,
} from "#expo/vector-icons";
import { color } from "react-native-reanimated";
class Pulsars extends React.Component {
constructor(props) {
super(props);
this.state = {
selectAll: false,
cartItemsIsLoading: false,
cartItems: [
/* Sample data from walmart */
{
itemId: "1",
name: "Orid Dhall",
quantity: "1kg",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/81f17QBywiL._SL1500_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "2",
name: "Orid Dhall",
quantity: "500g",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/81f17QBywiL._SL1500_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "3",
name: "Toor Dhall",
quantity: "1kg",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/81ieFDa5gHL._SY550_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "4",
name: "Toor Dhall",
quantity: "500g",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/81ieFDa5gHL._SY550_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "5",
name: "Gram Dhall",
quantity: "1kg",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/udhayam-gram-dal-228x228-1.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "6",
name: "Gram Dhall",
quantity: "500g",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/05/udhayam-gram-dal-228x228-1.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "7",
name: "Moong Dhall",
quantity: "1kg",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/12/819D8piBVKL._SL1500_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
{
itemId: "8",
name: "Moong Dhall",
quantity: "500g",
status: "Currently Not Available",
thumbnailImage:
"https://annaistores.com/as_content/uploads/2020/12/819D8piBVKL._SL1500_.jpg",
qty: 5,
salePrice: "123",
checked: 0,
},
],
};
}
selectHandler = (index, value) => {
const newItems = [...this.state.cartItems]; // clone the array
newItems[index]["checked"] = value == 1 ? 0 : 1; // set the new value
this.setState({ cartItems: newItems }); // set new state
};
selectHandlerAll = (value) => {
const newItems = [...this.state.cartItems]; // clone the array
newItems.map((item, index) => {
newItems[index]["checked"] = value == true ? 0 : 1; // set the new value
});
this.setState({
cartItems: newItems,
selectAll: value == true ? false : true,
}); // set new state
};
deleteHandler = (index) => {
Alert.alert(
"Are you sure you want to delete this item from your cart?",
"",
[
{
text: "Cancel",
onPress: () => console.log("Cancel Pressed"),
style: "cancel",
},
{
text: "Delete",
onPress: () => {
let updatedCart = this.state.cartItems; /* Clone it first */
updatedCart.splice(
index,
1
); /* Remove item from the cloned cart state */
this.setState(updatedCart); /* Update the state */
},
},
],
{ cancelable: false }
);
};
quantityHandler = (action, index) => {
const newItems = [...this.state.cartItems]; // clone the array
let currentQty = newItems[index]["qty"];
if (action == "more") {
newItems[index]["qty"] = currentQty + 5;
} else if (action == "less") {
newItems[index]["qty"] = currentQty > 5 ? currentQty - 5 : 5;
}
this.setState({ cartItems: newItems }); // set new state
};
subtotalPrice = () => {
const { cartItems } = this.state;
if (cartItems) {
return cartItems.reduce(
(sum, item) =>
sum + (item.checked == 1 ? item.qty * item.salePrice : 0),
0
);
}
return 0;
};
render() {
const styles = StyleSheet.create({
centerElement: { justifyContent: "center", alignItems: "center" },
});
const { cartItems, cartItemsIsLoading, selectAll } = this.state;
return (
<View style={{ flex: 1, backgroundColor: "#f6f6f6" }}>
<View
style={{
flexDirection: "row",
backgroundColor: "#fff",
marginBottom: 10,
}}
>
<View style={[styles.centerElement, { width: 50, height: 50 }]}>
<Ionicons name="ios-cart" size={25} color="#000" />
</View>
<View style={[styles.centerElement, { height: 50 }]}>
<Text style={{ fontSize: 18, color: "#000" }}>Shopping Cart</Text>
</View>
</View>
{cartItemsIsLoading ? (
<View style={[styles.centerElement, { height: 300 }]}>
<ActivityIndicator size="large" color="#ef5739" />
</View>
) : (
<ScrollView>
{cartItems &&
cartItems.map((item, i) => (
<View
key={i}
style={{
flexDirection: "row",
backgroundColor: "#fff",
marginBottom: 2,
height: 120,
}}
>
<View style={[styles.centerElement, { width: 60 }]}>
<TouchableOpacity
style={[styles.centerElement, { width: 32, height: 32 }]}
onPress={() => this.selectHandler(i, item.checked)}
>
<Ionicons
name={
item.checked == 1
? "ios-checkmark-circle"
: "ios-checkmark-circle-outline"
}
size={25}
color={item.checked == 1 ? "#0faf9a" : "#aaaaaa"}
/>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: "row",
flexGrow: 1,
flexShrink: 1,
alignSelf: "center",
}}
>
<TouchableOpacity
onPress={() => {
/*this.props.navigation.navigate('ProductDetails', {productDetails: item})*/
}}
style={{ paddingRight: 10 }}
>
<Image
source={{ uri: item.thumbnailImage }}
style={[
styles.centerElement,
{ height: 60, width: 60, backgroundColor: "#eeeeee" },
]}
/>
</TouchableOpacity>
<View
style={{
flexGrow: 1,
flexShrink: 1,
alignSelf: "center",
}}
>
<Text numberOfLines={1} style={{ fontSize: 15 }}>
{item.name}
</Text>
<Text numberOfLines={1} style={{ color: "#8f8f8f" }}>
{item.quantity}
</Text>
<Text numberOfLines={1} style={{ color: "#333333" }}>
₹{item.qty * item.salePrice}
</Text>
<Text>{item.status}</Text>
<View style={{ flexDirection: "row" }}>
<TouchableOpacity
onPress={() => this.quantityHandler("less", i)}
style={{ borderWidth: 1, borderColor: "#cccccc" }}
>
<MaterialIcons
name="remove"
size={22}
color="#cccccc"
/>
</TouchableOpacity>
<Text
style={{
borderTopWidth: 1,
borderBottomWidth: 1,
borderColor: "#cccccc",
paddingHorizontal: 7,
paddingTop: 3,
color: "#bbbbbb",
fontSize: 13,
}}
>
{item.qty}
</Text>
<TouchableOpacity
onPress={() => this.quantityHandler("more", i)}
style={{ borderWidth: 1, borderColor: "#cccccc" }}
>
<MaterialIcons name="add" size={22} color="#cccccc" />
</TouchableOpacity>
</View>
</View>
</View>
<View style={[styles.centerElement, { width: 60 }]}>
<TouchableOpacity
style={[styles.centerElement, { width: 32, height: 32 }]}
onPress={() => this.deleteHandler(i)}
>
<Ionicons name="md-trash" size={25} color="#ee4d2d" />
</TouchableOpacity>
</View>
</View>
))}
</ScrollView>
)}
{!cartItemsIsLoading && (
<View
style={{
backgroundColor: "#fff",
borderTopWidth: 2,
borderColor: "#f6f6f6",
paddingVertical: 5,
}}
>
<View style={{ flexDirection: "row" }}>
<View style={[styles.centerElement, { width: 60 }]}>
<View
style={[styles.centerElement, { width: 32, height: 32 }]}
></View>
</View>
<View
style={{
flexDirection: "row",
flexGrow: 1,
flexShrink: 1,
justifyContent: "space-between",
alignItems: "center",
}}
></View>
</View>
<View style={{ flexDirection: "row" }}>
<View style={[styles.centerElement, { width: 60 }]}>
<TouchableOpacity
style={[styles.centerElement, { width: 32, height: 32 }]}
onPress={() => this.selectHandlerAll(selectAll)}
>
<Ionicons
name={
selectAll == true
? "ios-checkmark-circle"
: "ios-checkmark-circle-outline"
}
size={25}
color={selectAll == true ? "#0faf9a" : "#aaaaaa"}
/>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: "row",
flexGrow: 1,
flexShrink: 1,
justifyContent: "space-between",
alignItems: "center",
}}
>
<Text>Select All</Text>
<View
style={{
flexDirection: "row",
paddingRight: 20,
alignItems: "center",
}}
>
<Text style={{ color: "#8f8f8f" }}>SubTotal: </Text>
<Text>₹{this.subtotalPrice().toFixed(2)}</Text>
</View>
</View>
</View>
<View
style={{
flexDirection: "row",
justifyContent: "flex-end",
height: 32,
paddingRight: 20,
alignItems: "center",
}}
>
<TouchableOpacity
style={[
styles.centerElement,
{
backgroundColor: "#0faf9a",
width: 100,
height: 25,
borderRadius: 5,
},
]}
onPress={() => console.log("test")}
>
<Text style={{ color: "#ffffff" }}>Add to Cart</Text>
</TouchableOpacity>
</View>
</View>
)}
</View>
);
}
}
export default Pulsars;

Flatlist Multiple item Selection not working on React Native

I am creating a multi-select grid Flatlist and it seems to work fine in IOS phone but it doesn't work at all on Android phone. On IOS it can select an item when clicked, but on Android it just flickers when you select/click an item.
I am really, really can't figure it out. Please help.
Thank you,
[Flatlist-Grid as per code][1]
import {
View, TouchableOpacity, StyleSheet, Text, ScrollView,
Image,
} from 'react-native'
import { MaterialIcons } from '#expo/vector-icons';
export default class StoreSelector extends Component {
constructor() {
super()
this.state = {
dataList: [
{ name: 'exp: date', key: '#ffsdsf', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#01713f', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#fsdaff', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#00b0a6', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#ffgadsf', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#fdfdf', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#fsdff', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#ec008c', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#005baa', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#fceff', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#ffwf', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#000', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
{ name: 'exp: date', key: '#ea3440', image: <Image style={{ height: 110, width: 110, backgroundColor: 'red' }} /> },
]
}
}
componentDidMount() {
let arr = this.state.dataList.map((item, index) => {
this.isSelected = false
return { ...item }
})
this.setState({ dataList: arr })
}
selectionHandler = (ind) => {
const { dataList } = this.state
let arr = dataList.map((item, index) => {
if (ind == index) {
item.isSelected = !item.isSelected
}
return { ...item }
})
this.setState({ dataList: arr })
}
render() {
const { dataList } = this.state
return (
<View style={styles.scrollContainer}>
<ScrollView >
<View style={styles.container}>
{
dataList.map((item, index) => {
return (
<TouchableOpacity
key={item.key}
onPress={() => this.selectionHandler(index)}
style={styles.boxContainer}>
<View style={styles.img}>{item.image}</View>
<View>{item.isSelected ? <MaterialIcons name="check-box" size={24} color="#fbbe2f" /> : <MaterialIcons name="check-box-outline-blank" size={24} color="grey" />}</View>
</TouchableOpacity>
)
})
}
</View>
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
scrollContainer: {
flex: 1,
},
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
},
boxContainer: {
height: 110,
width: 110,
margin: 7,
},
img: {
elevation: 5,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
shadowColor: '#000',
shadowOffset: { width: 1, height: 2 },
shadowOpacity: .3,
shadowRadius: 3,
borderWidth: 0.5,
borderColor: '#eee'
}
})
[1]: https://i.stack.imgur.com/hrRVS.png
You have given elevation to image element which is appearing above your checkbox so on select action it gets selected but not visible as it is under the image.
Now question is how will you see the checkbox?
Option 1: Remove the elevation
img: {
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
shadowColor: '#000',
shadowOffset: { width: 1, height: 2 },
shadowOpacity: .3,
shadowRadius: 3,
borderWidth: 0.5,
borderColor: '#eee'
}
Option 2: Make the elevation of the icons higher then the image elevation
<View>
{item.isSelected ?
<MaterialIcons name="check-box" size={24} color="#fbbe2f" style={{elevation:10}}/>
:
<MaterialIcons name="check-box-outline-blank" size={24} color="grey" style={{elevation:10}}/>}
</View>

My row item updates itself automatically into the deleted item how to fix this?

I am new to react native and the problem i am facing is that when i
delete an item from the flatlist it deletes just fine but also does
update the item below it. It updates it into the item which was
deleted. What am i doing wrong?
CartScreen.js
This is my code for the cart screen
import React, { Component } from 'react';
import { View, Text, Picker, FlatList } from 'react-native';
import HeaderComp from '../components/HeaderComp'
import { Container, Content } from 'native-base';
import colors from '../assets/Colors';
import styles from '../assets/Styles';
import ButtonComp from '../components/ButtonComp';
import IconComp from '../components/IconComp'
import RowCartComp from '../components/RowCartComp';
class CartPage extends Component {
constructor(props) {
super(props);
this.state = {
cartList: [
{ name: 'Sub Item 1', image: require('../images/1.jpeg'), price: 100, remainingQty: 1 },
{ name: 'Sub Item 2', image: require('../images/2.jpeg'), price: 200, remainingQty: 2 },
{ name: 'Sub Item 3', image: require('../images/3.jpeg'), price: 300, remainingQty: 3 },
{ name: 'Sub Item 4', image: require('../images/4.jpeg'), price: 400, remainingQty: 4 },
{ name: 'Sub Item 5', image: require('../images/5.jpeg'), price: 500, remainingQty: 5 },
{ name: 'Sub Item 6', image: require('../images/6.jpeg'), price: 600, remainingQty: 6 },
{ name: 'Sub Item 7', image: require('../images/7.jpeg'), price: 700, remainingQty: 7 },
{ name: 'Sub Item 8', image: require('../images/8.jpeg'), price: 800, remainingQty: 8 },
{ name: 'Sub Item 9', image: require('../images/9.jpeg'), price: 900, remainingQty: 9 },
{ name: 'Sub Item 10', image: require('../images/10.jpeg'), price: 1000, remainingQty: 10 },
],
grandTotal: 0
}
}
componentWillMount() {
let total = 0;
for (let i = 0; i < this.state.cartList.length; i++) {
total = total + this.state.cartList[i].price;
}
this.setState({ grandTotal: total })
}
updateGrandTotal = (value, op) => {
if (op === 'add') {
this.setState({ grandTotal: this.state.grandTotal + value });
}
else if (op === 'sub') {
this.setState({ grandTotal: this.state.grandTotal - value })
}
}
deleteItem = (name) => {
this.setState(prevState => {
return {
cartList: prevState.cartList.filter(cartItem => {
return cartItem.name !== name;
})
}
})
}
render() {
return (
<Container>
<HeaderComp
headerTitle="CART"
showBackArrow={true}
showIcons={false}
backClick={
() => this.props.navigation.goBack()
} />
<Content>
<View style={styles.cartPickerStyle}>
<View style={{ flex: 0.1 }}>
<IconComp
name='location_icon'
color={colors.colorBlack}
size={30}
/>
</View>
<View style={{ flex: 0.9 }}>
<Picker
selectedValue={this.state.language}
style={{ height: 20 }}
onValueChange={(itemValue, itemIndex) =>
this.setState({ language: itemValue })
}>
<Picker.Item label="Address A" value="A" />
<Picker.Item label="Address B" value="B" />
<Picker.Item label="Address C" value="C" />
</Picker>
</View>
</View>
<FlatList
data={this.state.cartList}
renderItem={({ item }) =>
<RowCartComp
itemName={item.name.toUpperCase()}
itemImage={item.image}
itemPrice={item.price}
itemRemainingQty={item.remainingQty}
deleteItem={() => this.deleteItem(item.name)}
updateGrandTotal={this.updateGrandTotal}
/>
}
/>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
<View style={styles.cartSeparatorStyle} />
<Text style={styles.cashOnDeliveryTextStyle}>
{" Cash on delivery "}
</Text>
<View style={styles.cartSeparatorStyle} />
</View>
<View style={styles.cartGrandTotalViewStyle}>
<View style={{ flex: 0.6 }}>
<Text style={styles.cartTextStyle}>
{"Grand Total"}
</Text>
<Text style={styles.cartTextStyle}>
{"Delivery charges"}
</Text>
</View>
<View style={{ flex: 0.4, alignItems: 'flex-end' }}>
<Text style={styles.cartTextStyle}>
{this.state.grandTotal}
</Text>
<Text style={styles.cartTextStyle}>
{"+ 30"}
</Text>
<View style={{ height: 1, borderColor: colors.colorWhite, borderWidth: 1, width: '70%' }} />
<Text style={styles.cartTextStyle}>
{this.state.grandTotal + 30}
</Text>
</View>
</View>
<ButtonComp
buttonText={'Place order'}
buttonStyle={styles.cartButtonStyle}
textStyle={styles.cartButtonTextStyle} />
</Content>
</Container>
);
}
}
export default CartPage;
RowCartComp.js
This is my row item for the list used in the cart screen
import React, { Component } from 'react';
import { View, Image, Text, Alert, } from 'react-native';
import IconComp from '../components/IconComp'
import colors from '../assets/Colors'
class RowCartComp extends Component {
constructor(props) {
super(props);
this.state = {
qtyString: 1,
priceString: this.props.itemPrice,
remainingQty: this.props.itemRemainingQty
}
}
increaseQty = () => {
if (this.state.qtyString < this.props.itemRemainingQty) {
this.setState({
qtyString: this.state.qtyString + 1,
priceString: this.state.priceString + this.props.itemPrice,
remainingQty: this.state.remainingQty - 1
})
this.props.updateGrandTotal(this.props.itemPrice, 'add')
}
}
decreaseQty = () => {
if (this.state.qtyString != 1) {
this.setState({
qtyString: this.state.qtyString - 1,
priceString: this.state.priceString - this.props.itemPrice,
remainingQty: this.state.remainingQty + 1
})
this.props.updateGrandTotal(this.props.itemPrice, 'sub')
}
else {
Alert.alert(
'REMOVE ITEM?',
'Are you sure you want to remove ' + `${this.props.itemName.toLowerCase()}` + '?',
[
{ text: 'No' },
{ text: 'Yes', onPress: this.combinedFunction },
],
{ cancelable: true },
);
}
}
combinedFunction = () => {
this.props.deleteItem()
this.props.updateGrandTotal(this.props.itemPrice, 'sub')
}
render() {
return (
<View style={{ margin: 10, borderColor: colors.colorBlack, borderWidth: 1 }}>
<View style={{ flexDirection: 'row', margin: 10 }}>
<View>
<Image
style={{ height: 70, width: 70, borderRadius: 6, }}
// source={{ uri: imageURL }}
source={this.props.itemImage}
/>
</View>
<View style={{ flex: 0.6, flexWrap: 'wrap', justifyContent: 'center', marginLeft: 5 }}>
<Text style={{ fontSize: 20, fontWeight: 'bold', color: colors.colorBlack, marginBottom: 5 }}>
{this.props.itemName}
</Text>
</View>
<View style={{ flex: 0.4, alignItems: 'flex-end' }}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<IconComp
name='minus_icon'
color={colors.colorBlack}
size={20}
onPress={this.decreaseQty}
/>
<Text style={{ fontSize: 20, fontWeight: 'bold', color: colors.colorBlack, marginLeft: 10, marginRight: 10 }}>
{this.state.qtyString}
</Text>
<IconComp
name='plus_icon'
color={colors.colorBlack}
size={20}
onPress={this.increaseQty}
/>
</View>
</View>
</View>
<View style={{ flexDirection: 'row', position: 'absolute', bottom: 0, right: 5, alignItems: 'center' }}>
<Text style={{ fontSize: 14, fontWeight: 'bold', color: colors.colorPrimaryDark, marginRight: 15 }}>
{"Qty Left: " + (this.state.remainingQty - 1) }
</Text>
<Text style={{ fontSize: 20, fontWeight: 'bold', color: colors.colorBlack }}>
{"RS: " + `${this.state.priceString}`}
</Text>
</View>
</View>
);
}
}
export default RowCartComp;
Styles.js
This is the style file where i created the styles for the cart page.
import { StyleSheet } from 'react-native';
import colors from './Colors'
export default StyleSheet.create({
cartButtonStyle: {
margin: 10,
padding: 10,
backgroundColor: colors.colorPrimaryDark,
borderRadius: 26,
justifyContent: 'center',
alignItems: 'center',
elevation: 4, // Android
shadowColor: 'gray', // IOS
shadowOffset: { height: 1, width: 1 }, // IOS
shadowOpacity: 1, // IOS
shadowRadius: 1, //IOS
},
cartButtonTextStyle: {
fontSize: 24,
fontWeight: 'bold',
color: colors.colorBlack,
},
cartTextStyle: {
fontSize: 20,
color: colors.colorWhite,
fontWeight: 'bold',
margin: 5,
},
cashOnDeliveryTextStyle: {
fontSize: 18,
color: colors.colorBlack,
},
cartPickerStyle: {
margin: 10,
padding: 10,
borderRadius: 20,
borderWidth: 1,
borderColor: colors.colorBlack,
flexDirection: 'row',
alignItems: 'center'
},
cartSeparatorStyle: {
width: '30%',
height: 1,
borderStyle: 'dotted',
borderColor: colors.colorBlack,
borderWidth: 1,
borderRadius: 1
},
cartGrandTotalViewStyle: {
margin: 10,
backgroundColor: colors.colorPrimaryDark,
flexDirection: 'row',
padding: 5,
paddingTop: 10,
paddingBottom: 10
},
});
The icons i used are imported using icomoon app and i created a custom component for it.
The button i used i also created a custom component for it.
These are the screenshots of the problem i am facing.
When Sub Item 3 is deleted, Sub Item 4 take its properties like the quantity left and the price of Sub Item 3.
The key to this is using making your cartItem have a key property, or to set a keyextractor function on the FlatList. By doing so, react "knows" which item is deleted and can update the correct RowCartComp. If you forget to have key property (or don't have keyExtractor), react only has the index of the updated item and thus might re-use the wrong component of your array.
Check the FlatList documentation for more information.
The code you posted however, actually contains kind of a React anti-pattern: you're copying props into the state of your child component RowCartComp. This makes managing updates and diffing in the RowCartComp harder. It would be better to lift the increase and decrease functions into the parent container. That way all manipulation logic resides in CartScreen and the RowCartComp can simply be a functional component and nothing can go out-of-sync.
I turned the RowCartComp into a function component accepting only some props and having no internal state. It accepts all data and handler functions from the parent
RowCartComp.js
import React, { Component } from "react";
import { View, Image, Text, Alert } from "react-native";
import IconComp from "../components/IconComp";
import colors from "../assets/Colors";
// this is now a functional component receiving
// 1. the entire cart item including qty property
// 2. handler to delete
// 3. handlers to increase/decrease the quantity
const RowCartComp = ({ item, deleteItem, increaseQty, decreaseQty }) => {
return (
<View
style={{ margin: 10, borderColor: colors.colorBlack, borderWidth: 1 }}
>
<View style={{ flexDirection: "row", margin: 10 }}>
<View>
<Image
style={{ height: 70, width: 70, borderRadius: 6 }}
source={itemImage}
/>
</View>
<View
style={{
flex: 0.6,
flexWrap: "wrap",
justifyContent: "center",
marginLeft: 5
}}
>
<Text
style={{
fontSize: 20,
fontWeight: "bold",
color: colors.colorBlack,
marginBottom: 5
}}
>
{item.name}
</Text>
</View>
<View style={{ flex: 0.4, alignItems: "flex-end" }}>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<IconComp
name="minus_icon"
color={colors.colorBlack}
size={20}
onPress={decreaseQty}
/>
<Text
style={{
fontSize: 20,
fontWeight: "bold",
color: colors.colorBlack,
marginLeft: 10,
marginRight: 10
}}
>
{item.qty.toString()}
</Text>
<IconComp
name="plus_icon"
color={colors.colorBlack}
size={20}
onPress={increaseQty}
/>
</View>
</View>
</View>
<View
style={{
flexDirection: "row",
position: "absolute",
bottom: 0,
right: 5,
alignItems: "center"
}}
>
<Text
style={{
fontSize: 14,
fontWeight: "bold",
color: colors.colorPrimaryDark,
marginRight: 15
}}
>
{"Qty Left: " + (item.remainingQty - item.qty)}
</Text>
<Text
style={{ fontSize: 20, fontWeight: "bold", color: colors.colorBlack }}
>
{"RS: " + `${item.price}`}
</Text>
</View>
</View>
);
};
export default RowCartComp;
Additionally I adjusted the CartPage.js component to
calculate the grand total on every render, it is a consequence of the current cart list
the cart items all have a quantity and an id property so the flatlist can work
have a handler that can increase of decrease the quantity of a cart item. This is then passed to the individual items
CartPage.js
import React, { Component } from 'react';
import { View, Text, Picker, FlatList } from 'react-native';
import HeaderComp from '../components/HeaderComp'
import { Container, Content } from 'native-base';
import colors from '../assets/Colors';
import styles from '../assets/Styles';
import ButtonComp from '../components/ButtonComp';
import IconComp from '../components/IconComp'
import RowCartComp from '../components/RowCartComp';
class CartPage extends Component {
constructor(props) {
super(props);
this.state = {
cartList: [
{ id: 1, name: 'Sub Item 1', image: require('../images/1.jpeg'), price: 100, remainingQty: 1, qty: 1 },
{ id: 2, name: 'Sub Item 2', image: require('../images/2.jpeg'), price: 200, remainingQty: 2, qty: 1 },
{ id: 3, name: 'Sub Item 3', image: require('../images/3.jpeg'), price: 300, remainingQty: 3, qty: 1 },
{ id: 4, name: 'Sub Item 4', image: require('../images/4.jpeg'), price: 400, remainingQty: 4, qty: 1 },
{ id: 5, name: 'Sub Item 5', image: require('../images/5.jpeg'), price: 500, remainingQty: 5, qty: 1 },
{ id: 6, name: 'Sub Item 6', image: require('../images/6.jpeg'), price: 600, remainingQty: 6, qty: 1 },
{ id: 7, name: 'Sub Item 7', image: require('../images/7.jpeg'), price: 700, remainingQty: 7, qty: 1 },
{ id: 8, name: 'Sub Item 8', image: require('../images/8.jpeg'), price: 800, remainingQty: 8, qty: 1 },
{ id: 9, name: 'Sub Item 9', image: require('../images/9.jpeg'), price: 900, remainingQty: 9, qty: 1 },
{ id: 10, name: 'Sub Item 10', image: require('../images/10.jpeg'), price: 1000, remainingQty: 10, qty: 1 },
],
}
}
// we can just calculate this every render
calculateGrandTotal () => {
let total = 0;
this.state.cartList.forEach(item => {
const itemTotal =item.qty * item.price;
total += itemTotal;
});
return total;
};
adjustQuantity = (id, diff) => {
const index = this.state.cartList.findIndex(ci => ci.id === id);
const item = this.state.cartList[index];
const newItem = {
...this.state.cartList[index],
qty: item.qty + diff
};
// don't go above remaining quantity
if (newItem.qty > newItem.remainingQty) {
return;
}
// don't go below 0
if (newItem.qty < 0) {
return;
}
// copy list and insert new item with adjusted quantity
const newCartList = [...this.state.cartList];
newCartList.splice(index, 1, newItem)
this.setState({
cartList: newCartList,
})
};
deleteItem = (id) => {
this.setState(prevState => {
return {
cartList: prevState.cartList.filter(cartItem => {
return cartItem.id !== id;
})
}
})
}
render() {
// grand total is calculated on every render, as it is
// a consequence of the current cartList
const grandTotal = this.calculateGrandTotal();
return (
<Container>
<HeaderComp
headerTitle="CART"
showBackArrow={true}
showIcons={false}
backClick={
() => this.props.navigation.goBack()
} />
<Content>
<View style={styles.cartPickerStyle}>
<View style={{ flex: 0.1 }}>
<IconComp
name='location_icon'
color={colors.colorBlack}
size={30}
/>
</View>
<View style={{ flex: 0.9 }}>
<Picker
selectedValue={this.state.language}
style={{ height: 20 }}
onValueChange={(itemValue, itemIndex) =>
this.setState({ language: itemValue })
}>
<Picker.Item label="Address A" value="A" />
<Picker.Item label="Address B" value="B" />
<Picker.Item label="Address C" value="C" />
</Picker>
</View>
</View>
<FlatList
data={this.state.cartList}
keyExtractor={item => `cart_${item.id}`}
renderItem={({ item }) =>
<RowCartComp
item={item}
deleteItem={() => this.deleteItem(item.id)}
increaseQty={() => this.adjustQuantity(item.id, +1)}
decreaseQty={() => this.adjustQuantity(item.id, -1)}
/>
}
/>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
<View style={styles.cartSeparatorStyle} />
<Text style={styles.cashOnDeliveryTextStyle}>
{" Cash on delivery "}
</Text>
<View style={styles.cartSeparatorStyle} />
</View>
<View style={styles.cartGrandTotalViewStyle}>
<View style={{ flex: 0.6 }}>
<Text style={styles.cartTextStyle}>
{"Grand Total"}
</Text>
<Text style={styles.cartTextStyle}>
{"Delivery charges"}
</Text>
</View>
<View style={{ flex: 0.4, alignItems: 'flex-end' }}>
<Text style={styles.cartTextStyle}>
{grandTotal}
</Text>
<Text style={styles.cartTextStyle}>
{"+ 30"}
</Text>
<View style={{ height: 1, borderColor: colors.colorWhite, borderWidth: 1, width: '70%' }} />
<Text style={styles.cartTextStyle}>
{grandTotal + 30}
</Text>
</View>
</View>
<ButtonComp
buttonText={'Place order'}
buttonStyle={styles.cartButtonStyle}
textStyle={styles.cartButtonTextStyle} />
</Content>
</Container>
);
}
}
export default CartPage;
Hope this helps.

How to align one component to left and other to right (end of page) react native?

I'm making an app in React Native and I want align a circle with the end of page.
I want to make this:
But it's currently like this and only stays this way:
The complete view:
[
I already tried alignSelf, justifyContent and others but it doesn't work.
I tested this: How to align 2 react native elements, 1 being in the center and 1 on the beginning
But it won't work.
My code:
const ListProductsHeader = () => (
<View>
<View style={style.containerInfo}>
<View style={style.circle} />
<View>
<Text style={style.unityName}>SUPERMERCADO MACCARTNEY</Text>
<Text style={style.subInfo}>Categoria: Mercado</Text>
<Text style={style.subInfo}>Pedido Nº: 1245</Text>
</View>
</View>
<View style={style.containerProducts}>
<Text style={style.productName}>1x 42 - Coca Cola 2L</Text>
<View style={style.minus}></View>
</View>
</View>
);
CSS:
containerProducts:{
paddingTop: 40,
paddingLeft: 15,
flexDirection: 'row',
},
productName: {
alignSelf: 'flex-start',
},
minus:{
width: 20,
height: 20,
borderRadius: 20/2,
backgroundColor: 'red',
},
containerInfo:{
paddingTop:15,
flexDirection:'row',
paddingLeft: 15,
},
unityName:{
fontWeight: 'bold',
paddingLeft: 15,
},
subInfo:{
color: 'gray',
paddingLeft: 15,
},
circle: {
width: 50,
height: 50,
borderRadius: 50/2,
backgroundColor: 'red',
justifyContent: 'flex-end',
},
Lkke to suggest one thing that can help you with this problem
what you need to do is. Everthing is correct except the main view css
<View style={flexDirection:'row',justifyContent : 'space-between'}>
<View style={style.circle} />
<View>
<Text style={style.unityName}>SUPERMERCADO MACCARTNEY</Text>
<Text style={style.subInfo}>Categoria: Mercado</Text>
<Text style={style.subInfo}>Pedido Nº: 1245</Text>
</View>
</View>
<View style={style.containerProducts}>
<Text style={style.productName}>1x 42 - Coca Cola 2L</Text>
<View style={style.minus}></View>
</View>
try this may be it can help you
containerProducts: {
paddingTop: 40,
paddingLeft: 15,
flexDirection: 'row',
justifyContent: 'space-between',
},
Fully Customisable chat in React Native
import React, {Component} from 'react';
import {
Text,
StyleSheet,
View,
TextInput,
TouchableOpacity,
SafeAreaView,
FlatList,
} from 'react-native';
export default class CustomChatScreen extends Component {
state = {
messages: [
{
msg: 'Heloo',
id: Math.random(),
token: '',
email: '',
type: 'server',
},
{
msg: 'Server Message',
id: Math.random(),
token: '',
email: '',
type: 'server',
},
],
value: '',
};
sendMessageToServer = () => {
if (this.state.value !== '') {
let payload = {
msg: this.state.value,
id: Math.random(),
token: '',
email: '',
type: 'client',
};
let mydata = this.state.messages;
mydata.push(payload);
this.setState({
messages: mydata,
value: '',
});
}
};
renderFlatListItem = rowData => {
return (
<View style={styles.flatListContainerStyle}>
{rowData.item.type === 'client' ? (
<View style={styles.clientMsgStyle}>
<Text>{rowData.item.msg}</Text>
</View>
) : (
<View style={styles.serverMsgStyle}>
<Text>{rowData.item.msg}</Text>
</View>
)}
</View>
);
};
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.messages}
keyExtractor={(item, index) => index.toString()}
renderItem={this.renderFlatListItem}
/>
<View style={styles.sendMessageConatinerStyle}>
<TextInput
style={styles.sendMsgTextInputStyle}
value={this.state.value}
placeholder = {"please type here!"}
placeholderTextColor = {"#000"}
onChangeText={val => this.setState({value: val})}></TextInput>
<TouchableOpacity
style={styles.sendMsgButtonStyle}
onPress={this.sendMessageToServer}>
<Text>Send Message</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
sendMessageConatinerStyle: {
width: '100%',
height: 60,
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
backgroundColor: 'white',
flexDirection: 'row',
},
sendMsgTextInputStyle: {
backgroundColor: '#e0f2f1',
flex: 0.8,
borderTopLeftRadius: 62.5,
borderBottomLeftRadius: 62.5,
padding: 20,
},
sendMsgButtonStyle: {
flex: 0.2,
backgroundColor: '#80cbc4',
borderBottomRightRadius: 62.5,
borderTopRightRadius: 62.5,
fontSize: 18,
justifyContent: 'center',
alignItems: 'center',
},
flatListContainerStyle: {
backgroundColor: '#e0f7fa',
marginTop: 10,
},
clientMsgStyle: {
backgroundColor: '#ffab91',
borderRadius: 20,
padding: 15,
alignSelf: 'flex-end',
},
serverMsgStyle: {
backgroundColor: '#4fc3f7',
borderRadius: 20,
padding: 15,
alignSelf: 'flex-start',
},
});