I have a FlatList, and each item in the List has two radio buttons - one for ascending and one for descending. My code currently allows a user to select either ascending or descending for the first list item, but it will not allow any of the radio buttons to be selected for the other list items (note: only ONE radio button should be selected at any one time). This is because when a radio button is pressed, the state is only being updated with the value of the button ('asc' or 'desc') but not the index of the list item as well. I am struggling to figure out how to update both of these using either onPress (on the RadioButton), or onValueChange (on RadioButton.Group).
How can I update both of these states when a radio button is selected, so that the buttons will work on the other list items and not just the first one?
Link to Snack is here: https://snack.expo.dev/@steph510/multiple-react-radio-buttons
Code is below:
import {View, Text, Modal, StyleSheet, Button, FlatList,} from "react-native";
import { RadioButton } from "react-native-paper";
export default class Sortby extends React.Component {
constructor(props) {
super(props);
}
state = {
selectedIndex: 0,
radioButtonValue: 'asc',
};
onPress = (index) => {
this.setState({
selectedIndex: index,
});
}
onRadiochange = value => {
this.setState({
radioButtonValue: value,
});
};
datalist = () => {
const gridFieldArray = [
{"text":"Organization","key":"0.6722908010549572"},
{"text":"Document No","key":"0.13707867638770266"},
{"text":"Warehouse","key":"0.5240454674464342"},
{"text":"Business Partner","key":"0.09679684535706568"},
{"text":"Partner Address","key":"0.5778522746749319"},
{"text":"Movement Date","key":"0.40039870656646404"}
]
return gridFieldArray;
};
render() {
return (
<Modal visible={this.props.visible} transparent={true}>
<View style={styles.modalStyles}>
<View style={styles.fieldsContainer}>
<FlatList
data={this.datalist()}
extraData={this.state}
renderItem={(itemData) => {
const index = itemData.index;
return (
<View style={styles.fieldItem}>
<Text style={styles.fieldText}>{itemData.item.text}</Text>
<View style={styles.radioButtonContainer}>
<RadioButton.Group onValueChange={this.onRadiochange}>
<View style={styles.singleRadioButtonContainer}>
<Text>Asc</Text>
<RadioButton
color='#5d86d7'
value="asc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'asc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
<View style={styles.singleRadioButtonContainer}>
<Text>Desc</Text>
<RadioButton
color='#5d86d7'
value="desc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'desc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
</RadioButton.Group>
</View>
</View>
);
}}
alwaysBounceVertical={false}
/>
</View>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button title="OK" color={"#5d86d7"}></Button>
</View>
<View style={styles.button}>
<Button
title="Cancel"
color={"#5d86d7"}
onPress={this.props.onCancel}
></Button>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
modalStyles: {
height: "auto",
width: "90%",
flexDirection: "column",
justifyContent: "flex-start",
alignItems: "center",
backgroundColor: "#fff",
borderColor: "#777",
borderWidth: 1,
paddingTop: 15,
marginLeft: 20,
marginTop: 50,
},
fieldsContainer: {
width: "100%",
},
fieldItem: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: 12,
borderBottomWidth: 1,
borderBottomColor: "#ebebeb",
},
fieldText: {
color: "#444",
},
radioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
},
singleRadioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
marginRight: 10,
},
buttonContainer: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginTop: 20,
marginBottom: 20,
},
button: {
width: "20%",
marginHorizontal: 8,
},
});
I am adding my now working solution here:
import {View, Text, Modal, StyleSheet, Button, FlatList,} from "react-native";
import { RadioButton } from "react-native-paper";
export default class Sortby extends React.Component {
constructor(props) {
super(props);
}
state = {
selectedIndex: 0,
radioButtonValue: 'asc',
};
onPress = (index) => {
this.setState({
selectedIndex: index,
});
}
onRadiochange = (index, value) => {
this.setState({
radioButtonValue: value,
selectedIndex: index
});
};
datalist = () => {
const gridFieldArray = [
{"text":"Organization","key":"0.6722908010549572"},
{"text":"Document No","key":"0.13707867638770266"},
{"text":"Warehouse","key":"0.5240454674464342"},
{"text":"Business Partner","key":"0.09679684535706568"},
{"text":"Partner Address","key":"0.5778522746749319"},
{"text":"Movement Date","key":"0.40039870656646404"}
]
return gridFieldArray;
};
render() {
return (
<Modal visible={this.props.visible} transparent={true}>
<View style={styles.modalStyles}>
<View style={styles.fieldsContainer}>
<FlatList
data={this.datalist()}
extraData={this.state}
renderItem={(itemData) => {
const index = itemData.index;
return (
<View style={styles.fieldItem}>
<Text style={styles.fieldText}>{itemData.item.text}</Text>
<View style={styles.radioButtonContainer}>
<RadioButton.Group onValueChange={value => this.onRadiochange(index, value)}>
<View style={styles.singleRadioButtonContainer}>
<Text>Asc</Text>
<RadioButton
color='#5d86d7'
value="asc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'asc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
<View style={styles.singleRadioButtonContainer}>
<Text>Desc</Text>
<RadioButton
color='#5d86d7'
value="desc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'desc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
</RadioButton.Group>
</View>
</View>
);
}}
alwaysBounceVertical={false}
/>
</View>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button title="OK" color={"#5d86d7"}></Button>
</View>
<View style={styles.button}>
<Button
title="Cancel"
color={"#5d86d7"}
onPress={this.props.onCancel}
></Button>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
modalStyles: {
height: "auto",
width: "90%",
flexDirection: "column",
justifyContent: "flex-start",
alignItems: "center",
backgroundColor: "#fff",
borderColor: "#777",
borderWidth: 1,
paddingTop: 15,
marginLeft: 20,
marginTop: 50,
},
fieldsContainer: {
width: "100%",
},
fieldItem: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: 12,
borderBottomWidth: 1,
borderBottomColor: "#ebebeb",
},
fieldText: {
color: "#444",
},
radioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
},
singleRadioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
marginRight: 10,
},
buttonContainer: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginTop: 20,
marginBottom: 20,
},
button: {
width: "20%",
marginHorizontal: 8,
},
});```
This is the solution that I came up with. Thanks to all who assisted:
import {View, Text, Modal, StyleSheet, Button, FlatList,} from "react-native";
import { RadioButton } from "react-native-paper";
export default class Sortby extends React.Component {
constructor(props) {
super(props);
}
state = {
selectedIndex: 0,
radioButtonValue: 'asc',
};
onPress = (index) => {
this.setState({
selectedIndex: index,
});
}
onRadiochange = (index, value) => {
this.setState({
radioButtonValue: value,
selectedIndex: index
});
};
datalist = () => {
const gridFieldArray = [
{"text":"Organization","key":"0.6722908010549572"},
{"text":"Document No","key":"0.13707867638770266"},
{"text":"Warehouse","key":"0.5240454674464342"},
{"text":"Business Partner","key":"0.09679684535706568"},
{"text":"Partner Address","key":"0.5778522746749319"},
{"text":"Movement Date","key":"0.40039870656646404"}
]
return gridFieldArray;
};
render() {
return (
<Modal visible={this.props.visible} transparent={true}>
<View style={styles.modalStyles}>
<View style={styles.fieldsContainer}>
<FlatList
data={this.datalist()}
extraData={this.state}
renderItem={(itemData) => {
const index = itemData.index;
return (
<View style={styles.fieldItem}>
<Text style={styles.fieldText}>{itemData.item.text}</Text>
<View style={styles.radioButtonContainer}>
<RadioButton.Group onValueChange={value => this.onRadiochange(index, value)}>
<View style={styles.singleRadioButtonContainer}>
<Text>Asc</Text>
<RadioButton
color='#5d86d7'
value="asc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'asc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
<View style={styles.singleRadioButtonContainer}>
<Text>Desc</Text>
<RadioButton
color='#5d86d7'
value="desc"
status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'desc' ? 'checked' : 'unchecked'}
onPress={() => {this.onPress(index)}}
/>
</View>
</RadioButton.Group>
</View>
</View>
);
}}
alwaysBounceVertical={false}
/>
</View>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<Button title="OK" color={"#5d86d7"}></Button>
</View>
<View style={styles.button}>
<Button
title="Cancel"
color={"#5d86d7"}
onPress={this.props.onCancel}
></Button>
</View>
</View>
</View>
</Modal>
);
}
}
const styles = StyleSheet.create({
modalStyles: {
height: "auto",
width: "90%",
flexDirection: "column",
justifyContent: "flex-start",
alignItems: "center",
backgroundColor: "#fff",
borderColor: "#777",
borderWidth: 1,
paddingTop: 15,
marginLeft: 20,
marginTop: 50,
},
fieldsContainer: {
width: "100%",
},
fieldItem: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: 12,
borderBottomWidth: 1,
borderBottomColor: "#ebebeb",
},
fieldText: {
color: "#444",
},
radioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
},
singleRadioButtonContainer: {
flexDirection: "row",
justifyContent: "flex-start",
alignItems: "center",
marginRight: 10,
},
buttonContainer: {
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginTop: 20,
marginBottom: 20,
},
button: {
width: "20%",
marginHorizontal: 8,
},
});```