How to align Text in React Native - javascript

I'm trying to style my work, I've included a slug description now and simply hardcoded it in whilst I try to make it look better. I'm having two problems that I'm looking to resolve. I can't get the slug text to align between one another. And the second issue is that when it is took long it wraps and distorts everything, I'd rather it reduced down and showed an ellipsis (...) are these things achieveable?
import { StyleSheet, Text, View, FlatList, SafeAreaView, Image } from 'react-native'
export default function App() {
const present = [{
id: 1,
name: 'PresentOne',
slug: 'PresentOne Slug',
image: require('../assets/present.jpeg')
},
{
id:2,
name: 'PresentTwo',
slug: 'PresentTwo Slug',
image: require('../assets/present2.jpeg')
},
{
id:3,
name: 'PresentThree',
slug: 'PresentThree Slug',
image: require('../assets/present3.jpeg')
},
{
id:4,
name: 'PresentFour',
slug: 'PresentFour Slug',
image: require('../assets/present4.jpeg')
},
{
id:5,
name: 'PresentFive',
slug: 'PresentFive Slug',
image: require('../assets/present5.jpeg')
},
];
const onePresent = ( { item } ) => (
<View style={styles.item}>
<View style={styles.avatarContainer}>
<Image source = {item.image} style={styles.avatarContainer}/>
</View>
<Text style={styles.name}> {item.name}</Text>
<Text style={styles.slug}>{item.slug}</Text>
</View>
)
const headerComponent = () => {
return <Text style={styles.listHeadline}>Presents</Text>
}
const itemSeperator = () => {
return <View style = {styles.seperator}/>
}
return (
<SafeAreaView >
<FlatList
ListHeaderComponentStyle={styles.listHeader}
ListHeaderComponent={headerComponent}
data = { present }
renderItem = { onePresent }
ItemSeperatorComponent = { itemSeperator }
ListEmptyComponent = { <Text>Empty</Text>}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
slug:{
transform: [{translateX: -100}],
// alignContent: 'center',
flexDirection: 'column',
alignItems: 'center',
},
name:{
transform: [{translateY: -30},{translateX: 10}],
fontSize: 20,
},
listHeadline:{
color:'#333',
fontSize: 21,
fontWeight: 'bold',
},
item: {
flex:1,
flexDirection:'row',
alignItems:'center',
paddingVertical:13,
},
avatarContainer:{
backgroundColor:'#D9D9D9',
borderRadius:100,
height:89,
width:89,
justifyContent:'center',
alignItems: 'center',
margin:10,
},
listHeader:{
height:55,
alignItems:'center',
justifyContent: 'center'
},
seperator: {
height: 1,
width: '100%',
backgroundColor: '#CCC',
}
})

The textAlign prop is what I think you want. However I noticed you were using transform to position the text in your view and I found a way to layout your components so that you dont have to do so (demo).
import {
StyleSheet,
Text,
View,
FlatList,
SafeAreaView,
Image,
} from 'react-native';
export default function App() {
const present = [
{
id: 1,
name: 'PresentOne',
slug: 'PresentOne Slug',
image: require('./assets/snack-icon.png'),
},
{
id: 2,
name: 'PresentTwo',
slug: 'PresentTwo Slug',
image: require('./assets/snack-icon.png'),
},
{
id: 3,
name: 'PresentThree',
slug: 'PresentThree Slug',
image: require('./assets/snack-icon.png'),
},
{
id: 4,
name: 'PresentFour',
slug: 'PresentFour Slug',
image: require('./assets/snack-icon.png'),
},
{
id: 5,
name: 'PresentFive',
slug: 'PresentFive Slug',
image: require('./assets/snack-icon.png'),
},
];
const onePresent = ({ item }) => (
<View style={styles.item}>
<View style={styles.avatarContainer}>
<Image source={item.image} style={styles.avatarContainer} />
</View>
<View style={styles.slug}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.slug}>{item.slug}</Text>
</View>
</View>
);
const headerComponent = () => {
return <Text style={styles.listHeadline}>Presents</Text>;
};
const itemSeperator = () => {
return <View style={styles.seperator} />;
};
return (
<SafeAreaView>
<FlatList
ListHeaderComponentStyle={styles.listHeader}
ListHeaderComponent={headerComponent}
data={present}
renderItem={onePresent}
ItemSeperatorComponent={itemSeperator}
ListEmptyComponent={<Text>Empty</Text>}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
slug: {
// transform: [{translateX: -100}],
// alignContent: 'center',
flexDirection: 'column',
alignItems: 'center',
},
name: {
// transform: [{translateY: -30},{translateX: 10}],
fontSize: 20,
},
listHeadline: {
width: '100%',
color: '#333',
fontSize: 21,
fontWeight: 'bold',
},
item: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
paddingVertical: 13,
},
avatarContainer: {
backgroundColor: '#D9D9D9',
borderRadius: 100,
height: 89,
width: 89,
justifyContent: 'center',
alignItems: 'center',
margin: 10,
},
listHeader: {
height: 55,
alignItems: 'center',
justifyContent: 'center',
},
seperator: {
height: 1,
width: '100%',
backgroundColor: '#CCC',
},
});

Related

Notification Screen- There are three different text in one line (Two Text near to each other and the third text to be float on right) in react native

Notification Screen- There are three different text in one line (Two Text near to each other and the third text to be float on right) in react native.
I am trying to float the text on right in the same line and align all right. What it can be. there is no option of floating text in react-native.
import React from "react";
import { StyleSheet, Text, View, FlatList, Image } from "react-native";
import Header from "../components/Header";
export default function Notifications() {
const data = [
{
id: "1",
post_title: "Best practice",
avatar: "../assets/avatar-placeholder.png",
username: "Bilal Majeed",
category: "Management",
notification: "Liked your post",
time: "Now",
},
{
id: "2",
post_title: "Best practice",
avatar: "../assets/avatar-placeholder.png",
username: "Amna Yasir",
category: "Special Volunteer",
notification: "shared your post ",
time: "Now",
},
{
id: "3",
post_title: "Best practice",
avatar: "../assets/avatar-placeholder.png",
username: "Amna Yasir",
category: "Special Volunteer",
notification: "commented on your post",
time: "5 min ago",
},
{
id: "4",
post_title: "Best practice",
avatar: "../assets/avatar-placeholder.png",
username: "Abbas S.",
category: "Management",
notification: "is now following you",
time: "15 min ago",
},
{
id: "5",
post_title: "Best practice",
avatar: "../assets/avatar-placeholder.png",
username: "Abbas S.",
category: "Management",
notification: "like your post",
time: "35 min ago",
},
];
return (
<View>
<View style={styles.container}>
<Header title={"Notifications"} />
</View>
<FlatList
data={data}
keyExtractor={(item, index) => {
return index.toString();
}}
renderItem={({ item }) => {
return (
<View style={styles.mainBody}>
<View style={styles.singleNotification}>
<Image
style={styles.avatar}
source={require("../assets/avatar-placeholder.png")}
/>
<View style={styles.mainContent}>
<View style={styles.notificationHead}>
<Text style={styles.userName}>{item.username}</Text>
<Text style={styles.categoryText}>{item.category}</Text>
<Text style={styles.timeText}>{item.time}</Text>
</View>
<View>
<Text style={styles.notification}>{item.notification}</Text>
</View>
</View>
</View>
<View style={styles.hairLine} />
</View>
);
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
},
mainBody: {
alignContent: "center",
alignItems: "center",
},
singleNotification: {
paddingHorizontal: 9,
flexDirection: "row",
alignItems: "center",
width: 330,
height: 62,
backgroundColor: "#fff",
marginTop: 10,
},
avatar: {
width: 35,
height: 35,
borderRadius: 35 / 2,
},
notificationHead: {
flexDirection: "row",
alignItems: "baseline",
backgroundColor: "#eee",
},
userName: {
fontFamily: "Roboto",
fontSize: 14,
fontWeight: "700",
color: "#707070",
marginLeft: 11,
lineHeight: 18,
},
categoryText: {
fontFamily: "Roboto",
fontSize: 11,
fontWeight: "400",
color: "#4582C3",
marginLeft: 11,
},
timeText: {
position: "relative",
right: 0,
fontFamily: "Roboto",
fontSize: 11,
fontWeight: "400",
color: "#707070",
opacity: 0.7,
marginLeft: 11,
textAlign: "left",
},
notification: {
fontFamily: "Roboto",
fontSize: 12,
fontWeight: "400",
color: "#707070",
marginLeft: 11,
lineHeight: 18,
},
hairLine: {
alignContent: "center",
padding: 0,
marginTop: 15,
width: "100%",
height: 2,
opacity: 0.5,
backgroundColor: "#eee",
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/0.14.0/react-dom.min.js"></script>
/*
[UI design ss][1]
[1]: https://i.stack.imgur.com/eM5Lk.png */
you can float something using position: "absolute", zindex: 1 and then align it left or right using top: 0, right:0
so your code should look something like this for floating text on right top
floatingComp: {
position: 'absolute',
zindex: 1,
top: 0,
right: 0,
},

Flatlist scroll doesn't work on android emulator

Im trying to create a horizontal flatlist. The code below does work in online editor but not on my emulator. I couldn't figure out if the problem is due to my code or the emulator. I tried remove horizontal property but still it doesn't work vertically. I replaced SafeAreaView with ScrollView but I took same result. Control the styles and removed all styles and tested without styles but again I couldn't scroll it.
export const Stories = () => {
const stories = [
{
id: 1,
name: "Name1",
image: "https://xsgames.co/randomusers/avatar.php?g=male",
},
{
id: 2,
name: "Name2",
image: "https://xsgames.co/randomusers/avatar.php?g=female",
},
{
id: 3,
name: "Name3",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 4,
name: "Name4",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 5,
name: "Name5",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 6,
name: "Name6",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 7,
name: "Name7",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 8,
name: "Name8",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
{
id: 9,
name: "Name9",
image: "https://xsgames.co/randomusers/avatar.php?g=pixel ",
},
];
const singleStory = ({ item }) => {
return (
<View style={styles.story}>
<View style={styles.avatarContainer}>
<Image source={{ uri: item.image }} style={styles.avatar} />
</View>
<Text>{item.name}</Text>
</View>
);
};
return (
<SafeAreaView style={styles.container}>
<FlatList
horizontal
data={stories}
renderItem={singleStory}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
borderColor: "grey",
borderBottomWidth: 0.9,
borderTopWidth: 0.9,
},
story: {
padding: 10,
alignItems: "center",
},
avatarContainer: {
height: 60,
width: 63,
justifyContent: "center",
alignItems: "center",
},
avatar: {
borderRadius: 50,
height: 50,
width: 50,
},
});
Add flex:1 in container, as you need to fix dimension of the view
container: {
borderColor: "grey",
borderBottomWidth: 0.9,
borderTopWidth: 0.9,
flex:1
},

Change Styling (background color) when buttons are tapped in React Native

I want to set the background color of the round/oval TouchableOpacity buttons beneath the headings to blue when they are tapped by the user, and no background color when they are not tapped. I have heard that this can be achieved by managing the states of the component itself.
Here is my code for reference:
import React, {useState} from 'react';
import {
StyleSheet,
Text,
View,
Button,
FlatList,
Dimensions,
TouchableOpacity,
Image,
} from 'react-native';
import Modal from 'react-native-modal';
const {width: screenWidth} = Dimensions.get('screen');
// screen width Multiply by 0.8
const Footer = () => {
return (
<View>
<Text style={{color: '#fff', fontSize: 20}}>Reviews</Text>
<View style={{flexDirection: 'row', alignItems: 'center', marginTop: 20}}>
<Image
source={require('../assets/five-stars.png')}
style={{width: 90, height: 18}}
/>
<Text style={{marginLeft: 10}}>& Up</Text>
</View>
<View style={{flexDirection: 'row', marginTop: 30}}>
<TouchableOpacity
style={{
backgroundColor: '#525252',
width: 200,
paddingTop: 20,
paddingBottom: 20,
alignItems: 'center',
borderTopLeftRadius: 22,
}}>
<Text>Reset</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: '#00ACED',
width: 200,
alignItems: 'center',
paddingTop: 20,
paddingBottom: 20,
borderTopRightRadius: 23,
}}>
<Text>Apply</Text>
</TouchableOpacity>
</View>
</View>
);
};
const renderItem = ({item: {title, data, key}}) => (
<View>
<Text style={styles.headingText}>{title}</Text>
<View style={styles.item}>
{data.map(el => (
<TouchableOpacity
key={el.key}
style={[
{
backgroundColor: el.isCheck ? '#00ACED' : 'transparent',
padding: 20,
borderColor: '#185268',
borderWidth: 2,
borderRadius: 40,
marginBottom: 10,
marginRight: 10,
},
]}>
<Text style={styles.btnText}>{el.name}</Text>
</TouchableOpacity>
))}
</View>
</View>
);
const SandboxScreen = () => {
const [isModalVisible, setModalVisible] = useState(false);
const [data, setData] = useState([
{
key: 'id-1',
title: 'Workshop Category',
data: [
{name: 'BodyShops', isCheck: false, key: 'id-5'},
{name: 'Electric Cars', isCheck: true, key: 'id-6'},
{name: 'Performance Shops', isCheck: false, key: 'id-7'},
],
},
{
key: 'id-2',
title: 'Vehicle Category',
data: [
{name: 'Cars', isCheck: false, key: 'id-8'},
{name: 'Trucks', isCheck: true, key: 'id-9'},
{name: 'Motorbikes', isCheck: false, key: 'id-10'},
],
},
{
key: 'id-3',
title: 'Services',
data: [
{name: 'Accident Repair', isCheck: false, key: 'id-11'},
{name: 'AC System Diagnosis', isCheck: false, key: 'id-12'},
{name: 'Car Polishing / Detailing', isCheck: false, key: 'id-13'},
{name: 'Electric / Hybrid System Repair', isCheck: true, key: 'id-14'},
{name: 'General Mechanical Work', isCheck: true, key: 'id-15'},
],
},
{
key: 'id-4',
title: 'Brands',
data: [
{name: 'FORD', isCheck: false, key: 'id-16'},
{name: 'BMW', isCheck: false, key: 'id-17'},
{name: 'BMW', isCheck: false, key: 'id-18'},
{name: 'AUDI', isCheck: false, key: 'id-19'},
{name: 'JAGUAR', isCheck: false, key: 'id-20'},
{name: 'FERRARI', isCheck: true, key: 'id-21'},
{name: 'LAMBORGHINI', isCheck: false, key: 'id-22'},
],
},
]);
const toggleModal = () => {
setModalVisible(prevState => !prevState);
};
return (
<View
style={[
{
flex: 1,
backgroundColor: '#252525',
},
]}>
<View style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.key}
ListFooterComponent={Footer}
/>
</View>
{/* <Button title="Show modal" onPress={toggleModal} />
<Modal
isVisible={isModalVisible}
animationIn="slideInRight"
animationOut="slideOutRight"
animationInTiming={500}
animationOutTiming={500}
hasBackdrop={true}
backdropColor="#252525"
backdropOpacity={0.8}
backdropTransitionInTiming={500}
backdropTransitionOutTiming={500}
onBackdropPress={() => setModalVisible(false)}
style={{alignItems: 'flex-end', margin: 0}}>
<View
style={{
backgroundColor: 'white',
flex: 1,
paddingTop: 50,
width: screenWidth * 0.7,
}}>
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
</View>
</Modal> */}
</View>
);
};
export default SandboxScreen;
const styles = StyleSheet.create({
container: {},
button: {
backgroundColor: 'green',
padding: 13,
},
headingText: {
color: '#fff',
fontSize: 20,
marginBottom: 20,
},
item: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: 40,
},
});
Please anyone guide me on how this can be achieve by providing code example related to my above code.
Here is your original solution: Snack
import React, { useState, useEffect } from 'react';
import {
StyleSheet,
Text,
View,
Button,
FlatList,
Dimensions,
TouchableOpacity,
SectionList,
Image,
} from 'react-native';
// import Modal from 'react-native-modal';
const { width: screenWidth } = Dimensions.get('screen');
// screen width Multiply by 0.8
const SandboxScreen = () => {
const [isModalVisible, setModalVisible] = useState(false);
const [data, setData] = useState([
{
key: 'id-1',
title: 'Workshop Category',
data: [
{ name: 'BodyShops', isCheck: false, key: 'id-5' },
{ name: 'Electric Cars', isCheck: true, key: 'id-6' },
{ name: 'Performance Shops', isCheck: false, key: 'id-7' },
],
},
{
key: 'id-2',
title: 'Vehicle Category',
data: [
{ name: 'Cars', isCheck: false, key: 'id-8' },
{ name: 'Trucks', isCheck: true, key: 'id-9' },
{ name: 'Motorbikes', isCheck: false, key: 'id-10' },
],
},
{
key: 'id-3',
title: 'Services',
data: [
{ name: 'Accident Repair', isCheck: false, key: 'id-11' },
{ name: 'AC System Diagnosis', isCheck: false, key: 'id-12' },
{ name: 'Car Polishing / Detailing', isCheck: false, key: 'id-13' },
{
name: 'Electric / Hybrid System Repair',
isCheck: true,
key: 'id-14',
},
{ name: 'General Mechanical Work', isCheck: true, key: 'id-15' },
],
},
{
key: 'id-4',
title: 'Brands',
data: [
{ name: 'FORD', isCheck: false, key: 'id-16' },
{ name: 'BMW', isCheck: false, key: 'id-17' },
{ name: 'BMW', isCheck: false, key: 'id-18' },
{ name: 'AUDI', isCheck: false, key: 'id-19' },
{ name: 'JAGUAR', isCheck: false, key: 'id-20' },
{ name: 'FERRARI', isCheck: true, key: 'id-21' },
{ name: 'LAMBORGHINI', isCheck: false, key: 'id-22' },
],
},
]);
const Footer = () => {
return (
<View>
<Text style={{ color: '#fff', fontSize: 20 }}>Reviews</Text>
<View
style={{ flexDirection: 'row', alignItems: 'center', marginTop: 20 }}>
<Text style={{ marginLeft: 10 }}>& Up</Text>
</View>
<View style={{ flexDirection: 'row', marginTop: 30 }}>
<TouchableOpacity
onPress={() => {
setData((prev) => {
//Here I have update your all isCheck prop to false;
let dat = prev.map((item, index) =>
item.data.map((v) => (v.isCheck = false))
);
return [...prev];
});
}}
style={{
backgroundColor: '#525252',
width: 200,
paddingTop: 20,
paddingBottom: 20,
alignItems: 'center',
borderTopLeftRadius: 22,
}}>
<Text>Reset</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
//You can call an API to store your results or directly save the results in your Storage.
alert('Results has been applied!');
}}
style={{
backgroundColor: '#00ACED',
width: 200,
alignItems: 'center',
paddingTop: 20,
paddingBottom: 20,
borderTopRightRadius: 23,
}}>
<Text>Apply</Text>
</TouchableOpacity>
</View>
</View>
);
};
const renderItem = ({ item: { title, data, key }, index }) => (
<View>
<Text style={styles.headingText}>{title}</Text>
<View style={styles.item}>
{data.map((el) => (
<TouchableOpacity
onPress={() => {
setData((prev) => {
el.isCheck = !el.isCheck; // `!` means if a value is true then make it false else make it true;
let dat = [el, ...prev[index].data];
// Here I'm spreading the both objects and merging the data;
return [...prev];
// Retruned the updated values by spreading it.
});
}}
key={el.key}
style={[
{
backgroundColor: el.isCheck ? '#00ACED' : 'transparent',
padding: 20,
borderColor: '#185268',
borderWidth: 2,
borderRadius: 40,
marginBottom: 10,
marginRight: 10,
},
]}>
<Text style={styles.btnText}>{el.name}</Text>
</TouchableOpacity>
))}
</View>
</View>
);
const toggleModal = () => {
setModalVisible((prevState) => !prevState);
};
return (
<View
style={[
{
flex: 1,
backgroundColor: '#252525',
},
]}>
<View style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.key}
ListFooterComponent={Footer}
/>
</View>
{/* <Button title="Show modal" onPress={toggleModal} />
<Modal
isVisible={isModalVisible}
animationIn="slideInRight"
animationOut="slideOutRight"
animationInTiming={500}
animationOutTiming={500}
hasBackdrop={true}
backdropColor="#252525"
backdropOpacity={0.8}
backdropTransitionInTiming={500}
backdropTransitionOutTiming={500}
onBackdropPress={() => setModalVisible(false)}
style={{alignItems: 'flex-end', margin: 0}}>
<View
style={{
backgroundColor: 'white',
flex: 1,
paddingTop: 50,
width: screenWidth * 0.7,
}}>
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
</View>
</Modal> */}
</View>
);
};
export default SandboxScreen;
const styles = StyleSheet.create({
container: {},
button: {
backgroundColor: 'green',
padding: 13,
},
headingText: {
color: '#fff',
fontSize: 20,
marginBottom: 20,
},
item: {
display: 'flex',
flexDirection: 'row',
marginBottom: 40,
},
});

how to create a radio button section with a data table in react native?

I would like to create a page like this in react native however I don't know how I could implement the radio buttons with data that looks like the following code. an idea of ​​how I could go about itenter image description here
My data looks like this with an option title first then the radio button to choose. To make it simple I would like to create a section with a title and radio buttons that and the data I get them in a table like this one
const products = [
{
id: 1,
title : 'Boisson',
data : [
{
label: 'Coca Cola',
price: '500 KMF',
},
{
label: 'Fanta',
price: '250 KMF',
},
{
label: 'Sprite',
price: '200 KMF',
},
]
},
{
id: 2,
title : 'Boisson',
data : [
{
label: 'Coca Cola',
price: '500 KMF',
},
{
label: 'Fanta',
price: '250 KMF',
},
{
label: 'Sprite',
price: '200 KMF',
},
]
},
];
Thank's for your help
You can use react-native-paper radio button check my example:
import React, { Component } from 'react';
import { Text, StyleSheet, View } from 'react-native';
import { RadioButton } from 'react-native-paper';
const products = [
{
id: 1,
title: 'Soft Drinks',
data: [
{
label: 'Coca Cola',
price: '500 KMF',
},
{
label: 'Fanta',
price: '250 KMF',
},
{
label: 'Sprite',
price: '200 KMF',
},
]
},
{
id: 2,
title: 'Juices',
data: [
{
label: 'Mango',
price: '500 KMF',
},
{
label: 'Orange',
price: '250 KMF',
},
{
label: 'Strawberry',
price: '200 KMF',
},
]
},
];
export default class DrinkSelector extends Component {
checkDrink(drink, object) {
var i;
for (i = 0; i < object.length; i++) {
if (object[i].isChecked === 'checked') {
object[i].isChecked = 'unchecked';
}
}
drink.isChecked = "checked";
this.setState({ refresh: true });
}
render() {
return (
<View style={{ flex: 1, padding: 20, backgroundColor: "#f2f2f2" }}>
{products.map((object, d) =>
<View key={d} style={{ justifyContent: 'space-between' }}>
<Text style={{ fontSize: 18, marginBottom: 20 }}>{object.title}</Text>
{object.data.map((drink, i) =>
<View key={i} style={styles.drinkCard}>
<RadioButton value={drink.price} status={drink.isChecked} onPress={() => this.checkDrink(drink, object.data)} />
<Text style={{ fontSize: 20, paddingLeft: 10 }}>{drink.label}</Text>
</View>
)}
</View>
)}
</View>
)
}
}
const styles = StyleSheet.create({
drinkCard: {
paddingLeft: 6,
alignItems: 'center',
flexDirection: 'row',
marginBottom: 16,
backgroundColor: 'white',
height: 55,
elevation: 1,
borderRadius: 4,
}
})

I'm unable to change states on switches inside ListItem component

What i'm trying to do is to list an array with multiple items, inside this component, and this array contains a boolean state for each individual item, like this.
items : {
"ISA InterChile" : [
{
key : '7843',
name : "ISA APP RRHH",
fav: false
},
{
key : '7844',
name : "Garantia y Obligaciones",
fav: false
},
{
key : '7855',
name : "Que se yo",
fav: true
},
{
key : '7899',
name : "Random",
fav: true
}
],
"DSAC Chile" : [
{
key : '5022',
name: 'ADAM RRHH',
fav: true
},
{
key : '5023',
name: 'Name of Project 4',
fav: false
}
],
"Banco BCI" : [
{
key : '1101',
name: 'Name of Project 3',
fav: false
},
{
key : '1014',
name: 'Name of Project 4',
fav: false
},
{
key : '1170',
name: 'Name of Project 5',
fav: false
},
{
key : '1033',
name: 'Name of Project 6',
fav: false
},
{
key : '1101',
name: 'Name of Project 7',
fav: false
},
{
key : '1014',
name: 'Name of Project 8',
fav: false
},
{
key : '1170',
name: 'Name of Project 9',
fav: false
},
{
key : '1033',
name: 'Name of Project 10',
fav: false
}
]
},
But whenever i try to change states, it immediately changes back to its previous state, this is the code.
{
this.state.items[this.state.SeleccionClientes].map(value => (
<ListItem
containerStyle={{backgroundColor: '#ffffff', width: widthPercentageToDP('87.1%'), height: 64, alignItems: 'center', justifyContent: 'center', alignSelf: 'center', marginTop: heightPercentageToDP('2.8%'), paddingHorizontal: 0}}
topDivider={false}
bottomDivider={true}
titleStyle={{
marginLeft: 0,
fontSize: 16,
fontWeight: "normal",
fontStyle: "normal",
lineHeight: 24,
letterSpacing: 0.15,
textAlign: "left",
color: "#707070"
}}
subtitleStyle={{
marginLeft: 0,
fontSize: 14,
fontWeight: "normal",
fontStyle: "normal",
lineHeight: 20,
letterSpacing: 0.25,
textAlign: "left",
color: "#c4c4c4"
}}
title={`${value.name}`}
subtitle={`ID ${value.key}`}
switch={{
value: value.fav, onValueChange: () => !value.fav
}}
/>
))
}
the this.state.SeleccionClientes is from a dropdown menu, where you select the item from items, and list you the items inside
EDIT: this is the whole view and code
import * as React from 'react';
import {View, Text, Image, StatusBar, SafeAreaView, TouchableOpacity, ScrollView, RefreshControl, FlatList} from 'react-native';
import { Header, ListItem } from 'react-native-elements';
import ModalDropdown from 'react-native-modal-dropdown';
import Images from '../../Assets/values/images';
import {
RFPercentage as rfp,
RFValue as rfv,
} from 'react-native-responsive-fontsize';
import {
widthPercentageToDP as wp,
heightPercentageToDP as hp,
heightPercentageToDP,
widthPercentageToDP,
} from 'react-native-responsive-screen';
import styles from '../../Assets/values/styles/HoursReport/ClientsProyects/ClientsProyectsStyle';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import DataManager from '../../../Util/CrossUtils/DataManager';
export default class ClientsProyectsScreen extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = {
items : {
"ISA InterChile" : [
{
key : '7843',
name : "ISA APP RRHH",
fav: false
},
{
key : '7844',
name : "Garantia y Obligaciones",
fav: false
},
{
key : '7855',
name : "Que se yo",
fav: true
},
{
key : '7899',
name : "Random",
fav: true
}
],
"DSAC Chile" : [
{
key : '5022',
name: 'ADAM RRHH',
fav: true
},
{
key : '5023',
name: 'Name of Project 4',
fav: false
}
],
"Banco BCI" : [
{
key : '1101',
name: 'Name of Project 3',
fav: false
},
{
key : '1014',
name: 'Name of Project 4',
fav: true
},
{
key : '1170',
name: 'Name of Project 5',
fav: false
},
{
key : '1033',
name: 'Name of Project 6',
fav: false
},
{
key : '1102',
name: 'Name of Project 7',
fav: true
},
{
key : '1114',
name: 'Name of Project 8',
fav: false
},
{
key : '1175',
name: 'Name of Project 9',
fav: false
},
{
key : '1303',
name: 'Name of Project 10',
fav: false
}
]
},
SeleccionClientes: '',
}
}
updateFav = item => {
const newData = this.state.items[this.state.SeleccionClientes];
const uodatedItem = newData.find(x => x.key === item.key);
uodatedItem.fav = !item.fav;
this.setState({ data: newData });
//You can also have a callback from parent component to update parent state
};
render() {
return (
<>
<StatusBar translucent backgroundColor="transparent" />
<SafeAreaView style={{backgroundColor: '#fafafa'}}/>
{/*
<Header
backgroundImage={Images.header_nav}
backgroundImageStyle={styles.HeaderImagenCP}
leftComponent={
<TouchableOpacity onPress={() => this.props.navigation.goBack()}>
<View><Image style={styles.HeaderHorizontal} source={Images.back}/></View>
</TouchableOpacity>
}
centerComponent={{text: 'Imputar horas', ellipsizeMode: 'clip', style: styles.HeaderHoursReportCP }}
placement='center'
/>
*/}
<View style={styles.ContainerBackground}>
<View style={{flexDirection: 'row'}}>
<View style={{alignItems: 'flex-start', justifyContent: 'flex-start', alignSelf: 'flex-start', marginTop: heightPercentageToDP('2.2%'), marginLeft: widthPercentageToDP('6.3%')}}>
<Text style={{
fontSize: 18,
fontWeight: "500",
fontStyle: "normal",
lineHeight: 35,
letterSpacing: 0,
textAlign: "left",
color: "#707070"
}}>Proyectos</Text>
</View>
<TouchableOpacity style={{position: 'absolute', alignItems: 'flex-end', justifyContent: 'flex-end', alignSelf: 'flex-end', paddingBottom: heightPercentageToDP('0.5%'), left: widthPercentageToDP('90%')}} onPress={() => this.props.navigation.goBack()}>
<Image source={Images.close_modal}/>
</TouchableOpacity>
</View>
<KeyboardAwareScrollView
keyboardShouldPersistTaps="handled"
enableOnAndroid={true}>
{/*
<View style={{alignItems: 'flex-end', justifyContent: 'flex-end', alignSelf: 'flex-end', marginRight: widthPercentageToDP('6.3%')}}>
<TouchableOpacity onPress={() => this.props.navigation.goBack()}>
<Image source={Images.close_modal}/>
</TouchableOpacity>
</View>
*/}
<View style={styles.Left}>
<Text style={styles.TituloInputOnBlur}>Cliente</Text>
</View>
<View style={styles.Center}>
<ModalDropdown
dropdownTextStyle={styles.dropdownTextStyle}
dropdownTextHighlightStyle={styles.dropdownTextHighlightStyle}
defaultValue={'Seleccionar'}
style={styles.dropStyle}
textStyle={{
padding: 0,
margin: 0,
fontSize: rfv(16),
paddingVertical: hp('1.2%'),
fontWeight: 'normal',
fontStyle: 'normal',
textAlign: 'left',
//color: Motivo != 'Seleccionar' ? '#1a1a1a' : '#c4c4c4',
}}
onSelect={(index, value) => this.setState({SeleccionClientes: value})}
options={Object.keys(this.state.items)}
/>
</View>
<View>
{
this.state.SeleccionClientes !== '' ?
<View>
{
<FlatList
data={this.state.items[this.state.SeleccionClientes]}
renderItem={({item, index}) => (
<ListItem
containerStyle={{backgroundColor: '#fafafa', width: widthPercentageToDP('87.1%'), height: 64, alignItems: 'center', justifyContent: 'center', alignSelf: 'center', marginTop: heightPercentageToDP('2.8%'), paddingHorizontal: 0}}
topDivider={false}
bottomDivider={true}
titleStyle={{
marginLeft: 0,
fontSize: 16,
fontWeight: "normal",
fontStyle: "normal",
lineHeight: 24,
letterSpacing: 0.15,
textAlign: "left",
color: "#707070"
}}
subtitleStyle={{
marginLeft: 0,
fontSize: 14,
fontWeight: "normal",
fontStyle: "normal",
lineHeight: 20,
letterSpacing: 0.25,
textAlign: "left",
color: "#c4c4c4"
}}
title={`${item.name}`}
subtitle={`ID ${item.key}`}
switch={{
//trackColor: {false: "#767577", true: "#81b0ff"},
//thumbColor: item.fav ? "#1062cc" : "#f4f3f4",
value: item.fav[index],
onValueChange: () => {this.updateFav(item)}
}}
/>
)}
/>
}
</View>
:
<View style={{alignItems: 'center', justifyContent: 'center', alignSelf: 'center'}}>
<View style={{marginTop: heightPercentageToDP('11%')}}>
<Image style={{marginBottom: heightPercentageToDP('2.8%')}} source={Images.sad_face}/>
</View>
<Text style={{
fontSize: 18,
fontWeight: "normal",
fontStyle: "normal",
lineHeight: 35,
letterSpacing: 0,
textAlign: "left",
color: "#c4c4c4"
}}>Sin proyectos activos</Text>
</View>
}
</View>
<View style={styles.BottomPush} />
</KeyboardAwareScrollView>
</View>
</>
);
}
}
You are not updating the state, your switch takes the value from the state object. And better use a flat list instead of map as its good in terms of performance. This will be a sample approach that you can take.
class CustomFlatList extends Component {
constructor(props) {
super(props);
this.state = {
data: this.props.data,
};
}
updateFav = item => {
const newData = [...this.state.data];
const uodatedItem = newData.find(x => x.key === item.key);
uodatedItem.fav = !item.fav;
this.setState({ data: newData });
//You can also have a callback from parent component to update parent state
};
render() {
return (
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
title={`${item.name}`}
subtitle={`ID ${item.key}`}
switch={{
value: item.fav,
onValueChange: () => this.updateFav(item),
}}
/>
)}
/>
);
}
}
--Updated code after full code
You will have to update the updateFav function as below.
updateFav = item => {
const newData = [...this.state.items[this.state.SeleccionClientes]];
const updateItem = newData.find(x => x.key === item.key);
updateItem.fav = !item.fav;
const updatedArray = Object.assign(this.state.items);
updatedArray[this.state.SeleccionClientes] = newData;
this.setState({ items: updatedArray });
};

Categories