Kanwarjeet Singh
Kanwarjeet Singh

Reputation: 745

React native, select one item from flatlist

I created a list of data in flatlist and I want that when user click on item it will select that only that item but it's selecting all item. I don't know where did I mistake. Below is my code.

const [state, setState] = useState({
    isLoading: false,
    search: '',
    isClicked: false,
  });
  const {isLoading, search, isClicked} = state;

  <FlatList
        data={data}
        style={{marginTop: moderateScaleVertical(23)}}
        keyExtractor={(data) => data.id.toString()}
        renderItem={({item}) => (
          <>
            {!isClicked && item.id ? (
              <TouchableOpacity
                style={styles.container}
                onPress={() => setState({isClicked: true})}>
                <View
                  style={{
                    width: moderateScale(18),
                    height: moderateScaleVertical(18),
                    backgroundColor: colors.blackOpacity20,
                    borderRadius: moderateScale(18 / 2),
                  }}
                />
                <Text
                  style={{
                    ...commonStyles.fontSize15,
                    color: colors.themeColor,
                    marginLeft: moderateScale(18),
                  }}>
                  {item.tag}
                </Text>
              </TouchableOpacity>
            ) : (
              <TouchableOpacity
                style={styles.container}
                onPress={() => setState({isClicked: false})}>
                <Image
                  source={imagePath.checkboxActive}
                  style={{
                    width: moderateScale(18),
                    height: moderateScaleVertical(18),

                    borderRadius: moderateScale(18 / 2),
                  }}
                />
                <Text
                  style={{
                    ...commonStyles.fontSize15,
                    color: colors.themeColor,
                    marginLeft: moderateScale(18),
                  }}>
                  {item.tag}
                </Text>
              </TouchableOpacity>
            )}
          </>
        )}
      />

I don't what I did wrong here. can someone please help

Upvotes: 0

Views: 1654

Answers (2)

Kleiton Pereira
Kleiton Pereira

Reputation: 105

You are using a state variable isClicked to check if an item is selected, but since that state is the same for the entire component, once the isClicked is set to true, all items of the Flatlist will be re-rendered as selected because they will be checking the same variable. What you could do to achieve your goal is to put a isClicked flag individually inside each item, so only the item's flag is set to true once you click on it.

Something like:

<FlatList
    data={data}
    style={{marginTop: moderateScaleVertical(23)}}
    keyExtractor={(data) => data.id.toString()}
    renderItem={({item}) => (
      <>
        {item.isClicked && item.id ? (
          <TouchableOpacity
            style={styles.container}
            onPress={() => item.isClicked = true}>
            <View
              style={{
                width: moderateScale(18),
                height: moderateScaleVertical(18),
                backgroundColor: colors.blackOpacity20,
                borderRadius: moderateScale(18 / 2),
              }}
            />
            <Text
              style={{
                ...commonStyles.fontSize15,
                color: colors.themeColor,
                marginLeft: moderateScale(18),
              }}>
              {item.tag}
            </Text>
          </TouchableOpacity>
        ) : (
          <TouchableOpacity
            style={styles.container}
            onPress={() => item.isClicked = false}>
            <Image
              source={imagePath.checkboxActive}
              style={{
                width: moderateScale(18),
                height: moderateScaleVertical(18),

                borderRadius: moderateScale(18 / 2),
              }}
            />
            <Text
              style={{
                ...commonStyles.fontSize15,
                color: colors.themeColor,
                marginLeft: moderateScale(18),
              }}>
              {item.tag}
            </Text>
          </TouchableOpacity>
        )}
      </>
    )}
  />

Upvotes: 1

Ivo
Ivo

Reputation: 2518

Your isClicked local state is common for all the elements of your list, meaning that if you trigger it all of them will have it as true.

The best way to solve this issue would be not to pass a boolean to isClicked but rather the item.id:

onPress={() => setState({isClicked: item.id})}>

and then

{isClicked !== item.id && item.id ? (

Also be careful, you are not maintenaing the state of search and isLoading with your way of updating the state, you should actually rather have:

onPress={() => setState({isLoading, search, isClicked: item.id})}>

If you need to handle multiple possible items clicked at the same time I'd recommend separating each item in their own component with their own isClicked state OR having an array of id for the isClicked values

Upvotes: 1

Related Questions