如何在 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!
   }
}

然后,当您在列表中呈现项目时,检查 属性 以确保该项目是否被选中。