Reputation: 628
I'm working on a react native project and I'm really new to this technology.
I have a dynamic list (data fetching from the server). Each item on that list has two buttons, "YES" and "NO" as follows
Scenario: If the user clicks the "YES" button that needs to be highlighted in green color, otherwise user clicked on the "NO" button style pick should be added to the "NO" button. Likewise, the user can select multiple buttons in that list as follows.
My problem is, Now If I select one button from my list, that color will appear to the complete list as follows. If 1st item "YES" button selected all the YES buttons will be displayed as follows.
I did lots of code changes to fix this issue, but they did not work for me.
I have added my code below, Please let me know where it is going wrong. Thanks in advance.
checkList.tsx
const [isYesButtonEnabled, setIsYesButtonEnabled] = useState(false);
const [isNoButtonEnabled, setIsNoButtonEnabled] = useState(false);
const [checkLisItems, setCheckListItems] = useState({
isLoading: true,
checklistData: null,
});
const yesClicked = () => {
setIsYesButtonEnabled(true);
setIsNoButtonEnabled(false);
}
const noClicked = () => {
setIsYesButtonEnabled(false);
setIsNoButtonEnabled(true);
}
<View style={{ flex: 4 }}>
<FlatList
showsHorizontalScrollIndicator={false}
data={checkLisItems.checklistData}
renderItem={({ item }) => {
return (
<InspectionCheckListItem
itemData={item}
yesClicked={() => yesClicked()}
noClicked={() => noClicked()}
isYesButtonEnabled={isYesButtonEnabled}
isNoButtonEnabled={isNoButtonEnabled}
/>
);
}}
keyExtractor={item => `${item.chelistid}`}
/>
</View>
InsprctionCheckListRow.tsx
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet, TextInput } from 'react-native';
import { COLORS, FONT_FAMILY } from '../../../../constants/Component.styles';
type props = {
isYesButtonEnabled?: boolean;
isNoButtonEnabled?: boolean;
yesClicked?: () => void;
noClicked?: () => void;
}
const InsprctionCheckListItem = props => {
return (
<View style={styles.container}>
<View style={{ flex: 1, alignSelf: 'center' }} >
<Text style={styles.allText}>{props.itemData.checklistName}</Text>
</View>
<View style={{ flex: 1, flexDirection: 'row', alignSelf: 'center', justifyContent: 'center' }} >
<TouchableOpacity style={props.isYesButtonEnabled ? styles.touchButtonClicked : styles.touchButton} onPress={props.yesClicked}>
<Text style={styles.touchButtonWithoutClick}>YES</Text>
</TouchableOpacity>
<TouchableOpacity style={props.isNoButtonEnabled ? styles.touchButtonClicked : styles.touchButton} onPress={props.noClicked}>
<Text style={styles.touchButtonWithoutClick}>NO</Text>
</TouchableOpacity>
</View>
<View style={{ flex: 1 }} >
<TextInput style={styles.textInput} onChangeText={props.changedText} defaultValue={props.itemData.remark}/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'flex-start',
flexDirection: 'row',
marginTop: '3%',
},
allText: {
fontSize: 20,
color: COLORS.BLUE_2C,
fontFamily: FONT_FAMILY.LIGHT,
justifyContent: 'center',
alignSelf: 'center'
},
textInput: {
fontSize: 20,
color: COLORS.BLUE_2C,
fontFamily: FONT_FAMILY.LIGHT,
borderWidth: 0.5,
borderRadius: 5,
borderColor: COLORS.BLUE_69,
backgroundColor: 'rgba(0,0,0,0)',
},
touchButton: {
width: 80,
height: 40,
borderRadius: 5,
borderWidth: 0.8,
borderColor: COLORS.ASH_AE,
justifyContent: 'center',
alignSelf: 'center',
textAlign: 'center',
margin: '0.2%',
backgroundColor: COLORS.ASH_AE,
},
touchButtonClicked: {
width: 80,
height: 40,
borderRadius: 5,
borderWidth: 0.8,
borderColor: COLORS.PINK,
justifyContent: 'center',
alignSelf: 'center',
textAlign: 'center',
backgroundColor: COLORS.PINK,
},
touchButtonWithoutClick: {
fontSize: 14,
color: COLORS.WHITE,
fontFamily: FONT_FAMILY.LIGHT,
justifyContent: 'center',
alignSelf: 'center',
textAlign: 'center'
}
});
export default InsprctionCheckListItem;
Sample Server Response
"ChecklistsItem": [
{
"chelistid": 123,
"ireqstId": 12,
"checklistName": "Name and address of the pharmacy",
"validity": "Valid",
"remark": null
}
],
Upvotes: 1
Views: 842
Reputation: 1866
If you pass one boolean state to all the choices , changing one will change the state which will affect all the choices connected to it. But you can push the item that has been choose (Yes) into an array and for each choice group check if that item exists in the choice array by array.findIndex() method, if it is then its yes if not then its no , check the following example:
//add new array that will carry the elements that marked as yes
const [arrayOfYes, setArrayOfYes] = useState([]);
//Modify yes clicked by pushing the clicked yes into the new array
const yesClicked = (element) => {
//Check first that it doesn't exist inside the array to avoid
//duplicates
const doesntExist = arrayOfYes.findIndex(x => x.chelistid ===
element.chelistid) === -1
if (doesntExist){
setArrayOfYes([...arrayOfYes, element]);
}
}
//Modify no clicked by remove the clicked no if it exists in the array
const noClicked = (element) => {
const index = arrayOfYes.findIndex(x => x.chelistid === element.
chelistid)
if (index !== -1){
//Remove the element from the array
var modifiedArray = [...arrayOfYes]
modifiedArray.splice(index, 1);
setArrayOfYes(modifiedArray)
}
}
//Pass the element parameter and update yes and no enabled
<InspectionCheckListItem
itemData={item}
yesClicked={() => yesClicked(item)}
noClicked={() => noClicked(item)}
//now check if the current item exists in the array by finding the index
isYesButtonEnabled={arrayOfYes.findIndex(x => x.chelistid === item.
chelistid)!== -1} //If the index = -1 that means the item doesn't exist
isNoButtonEnabled={arrayOfYes.findIndex(x => x.chelistid === item.
chelistid)== -1} //If The element is not yes then it is no
/>
Upvotes: 1
Reputation: 697
The problem in your code is: You are using one Y/N state to handle all the items in list!
So that, if one item in list changes the Y/N state, the others will change, because they share the same Y/N state for rendering.
My suggestion:
When you receive data from backend, you could append one more property to each item for handling Yes/No state, eg:
ChecklistsItem = dataResponse.map(item => {
return {
...item,
enabled: true // here!
}
}
Then, when you render item in list, check that property to ensure that the item is checked Yes or not.
Upvotes: 1