Problem with a list of selectable items that are stored in an array

Asked

Viewed 135 times

-3

Hello, I need to create a list where I can select one of the items and also deselect, but I’m having problems because the list only selects correctly if I select in ascending order and desiccate in descending order and I don’t understand where my mistake is. I need this list to be selectable/deselectable in any order.

LIST PRINT

Print da lista, O problema é que só consigo selecionar ela em ordem crescente e decrescente, e preciso poder selecionar em qualquer ordem.

LIST CODE

import React, { useState } from "react";
import {
  StyleSheet,
  SafeAreaView,
  View,
  Text,
  TouchableOpacity,
  FlatList,
  Image,
} from "react-native";

import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from "react-native-responsive-screen";

const LISTA = [
  {
    id:1,
    title: "Teste",
  },
  {
    id:2,
    title: "Teste2",
  },
  {
    id: 3,
    title: "Teste3",
  },
  {
    id: 4,
    title: "Teste 4",
  },
  {
    id: 5,
    title: "123",
  },
];

const Item = ({ item, onPress, style }) => (
  <TouchableOpacity onPress={onPress} style={[estiloLista.objetoLista, style]}>
    <Text style={{ color: "white", fontSize: 20 }}>ID :{item.id}</Text>
    <Text style={{ color: "black", fontSize: 20 }}>Titulo: {item.title}</Text>
  </TouchableOpacity>
);

const Lista = () => {
  const [idSelecionado, setIdSelecionado] = useState([0]);

  function adicionarItem(id: number) {
    if (idSelecionado.indexOf(id) === -1) {
      setIdSelecionado([...idSelecionado, id]);
      idSelecionado.sort();
      console.log("nova coleção é: " + idSelecionado);
    } else if (idSelecionado.indexOf(id) > -1) {
      idSelecionado.sort();
      idSelecionado.splice(idSelecionado.indexOf(id), 1); 
      setIdSelecionado([...idSelecionado]);
      console.log("id removido: ", id);
      console.log("nova coleção, apos removido é: ", idSelecionado);
    }
  }

  const renderItem = ({ item }) => {
    const backgroundColor =
      item.id === idSelecionado[item.id] ? "lightsteelblue" : "red";
    const icone =
      item.id === idSelecionado[item.id]
        ? require("../src/assets/icones/basic/check_bold.png")
        : null;

    return (
      <View
        style={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        <Item
          item={item}
          onPress={() => adicionarItem(item.id)}
          style={{ backgroundColor }}
        />

        <Image
          source={icone}
          style={{ position: "relative", top: "-50%", left: "-40%" }}
        />
      </View>
    );
  };

  return (
    <SafeAreaView>
      <FlatList
        data={LISTA}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
        extraData={idSelecionado}
      />
    </SafeAreaView>
  );
};
export default Lista;

const estiloLista = StyleSheet.create({
  container: {
    flex: 1,
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  textoLista: {
    fontSize: 24,
    textAlign: "center",
  },
  objetoLista: {
    width: wp("95%"),
    height: wp("15%"),
    backgroundColor: "lightsteelblue",
    borderRadius: 5,
    borderWidth: 2,
    borderColor: "grey",
    margin: 10,
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
});

THANK YOU ALL

2 answers

1

To make your logic easier, in your list you add an attribute selected thus:

const LISTA = [
  {
    id:1,
    title: "Teste",
    selected: false,
  },
  {
    id:2,
    title: "Teste2",
    selected: false,
  },
  {
    id: 3,
    title: "Teste3",
    selected: false,
  },
  {
    id: 4,
    title: "Teste 4",
    selected: false,
  },
  {
    id: 5,
    title: "123",
    selected: false,
  },
];

This variable will control whether the item in the list is selected or not, you will use it for your color logic and icon in this way:

const backgroundColor = item.selected ? "lightsteelblue" : "red";

Now to change when the item is selected or not you will need to scroll through the list, find the respective item and change the attribute selected. A way to do this can be like this:

function alteraItem(id: number) {
    LISTA.forEach((elemento) => {
        if(elemento.id === id) {
            if(elemento.selected){
                elemento.selected = false
            } else {
                elemento.selected = true
            }
        }
    })
    console.log("nova coleção é: " + LISTA);
}

-1

Use React States and create state to see if the item is selected or not, more or less like this.

// create your list with state true or false

const generateFilterWithState = (original, selected = []) => original.map(value => ({
  value,
  filterState: selected.includes(value)
}));

handleSelectAll (item) {
        this.setState((prevState) => ({
          itens: {
            ...prevState.itens,
            [item]: prevState.itens[item].map(
              ({ value, filterState }) => ({
                value,
                filterState: true
              })
            )
          }
        }));

  handleClearAll (item) {
    this.setState((prevState) => ({
      itens: {
        ...prevState.itens,
        [item]: prevState.itens[item].map(
          ({ value, filterState }) => ({
            value,
            filterState: false
          })
        )
      }
    }));
  }
  • 2

    Hi, this is stackoverflow in Portuguese. Click [Edit] and update your reply.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.