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