如何在 React Native FlatList 中一次处理一个按钮?
How to handle a single button at a time in React Native FlatList?
我正在做一个 React Native 项目,我对这项技术真的很陌生。
我有一个动态列表(从服务器获取数据)。该列表中的每个项目都有两个按钮,“是”和“否”,如下所示
场景:如果用户单击需要以绿色突出显示的“是”按钮,否则用户单击“否”按钮样式选择应添加到“否”按钮。同样,用户可以 select 该列表中的多个按钮,如下所示。
我的问题是,现在如果我 select 列表中的一个按钮,该颜色将出现在完整列表中,如下所示。如果第一项“YES”按钮 selected 所有 YES 按钮将显示如下。
我做了很多代码更改来解决这个问题,但它们对我不起作用。
我已经在下面添加了我的代码,请让我知道哪里出了问题。提前致谢。
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;
示例服务器响应
"ChecklistsItem": [
{
"chelistid": 123,
"ireqstId": 12,
"checklistName": "Name and address of the pharmacy",
"validity": "Valid",
"remark": null
}
],
如果您将一个布尔状态传递给所有选项,更改一个将更改状态,这将影响与其相关的所有选项。
但是您可以将已选择 (Yes) 的项目推送到一个数组中,并通过 array.findIndex() 方法为每个选择组检查该项目是否存在于选择数组中,如果存在则为是,如果不存在则为否,检查以下示例:
//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
/>
您的代码中的问题是:您正在使用 一个 Y/N 状态 来处理列表中的 所有项目 !
因此,如果列表中的一项更改 Y/N 状态,其他项也会更改,因为它们共享相同的 Y/N 状态进行渲染。
我的建议:
当你从后端接收数据时,你可以在每个项目上再追加一个属性来处理Yes/No状态,例如:
ChecklistsItem = dataResponse.map(item => {
return {
...item,
enabled: true // here!
}
}
然后,当您在列表中呈现项目时,检查 属性 以确保该项目是否被选中。
我正在做一个 React Native 项目,我对这项技术真的很陌生。
我有一个动态列表(从服务器获取数据)。该列表中的每个项目都有两个按钮,“是”和“否”,如下所示
场景:如果用户单击需要以绿色突出显示的“是”按钮,否则用户单击“否”按钮样式选择应添加到“否”按钮。同样,用户可以 select 该列表中的多个按钮,如下所示。
我的问题是,现在如果我 select 列表中的一个按钮,该颜色将出现在完整列表中,如下所示。如果第一项“YES”按钮 selected 所有 YES 按钮将显示如下。
我做了很多代码更改来解决这个问题,但它们对我不起作用。
我已经在下面添加了我的代码,请让我知道哪里出了问题。提前致谢。
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;
示例服务器响应
"ChecklistsItem": [
{
"chelistid": 123,
"ireqstId": 12,
"checklistName": "Name and address of the pharmacy",
"validity": "Valid",
"remark": null
}
],
如果您将一个布尔状态传递给所有选项,更改一个将更改状态,这将影响与其相关的所有选项。 但是您可以将已选择 (Yes) 的项目推送到一个数组中,并通过 array.findIndex() 方法为每个选择组检查该项目是否存在于选择数组中,如果存在则为是,如果不存在则为否,检查以下示例:
//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
/>
您的代码中的问题是:您正在使用 一个 Y/N 状态 来处理列表中的 所有项目 !
因此,如果列表中的一项更改 Y/N 状态,其他项也会更改,因为它们共享相同的 Y/N 状态进行渲染。
我的建议:
当你从后端接收数据时,你可以在每个项目上再追加一个属性来处理Yes/No状态,例如:
ChecklistsItem = dataResponse.map(item => {
return {
...item,
enabled: true // here!
}
}
然后,当您在列表中呈现项目时,检查 属性 以确保该项目是否被选中。