theDC
theDC

Reputation: 6484

FlatList single select cell

I followed the example from official docs, here is how to implement multiselection feature:

state = { selected: (new Map(): Map<string, boolean>) };

onPressItem = (id) => {
  this.setState((state) => {
    const selected = new Map(state.selected);
    selected.set(id, !selected.get(id)); 
    return { selected };
  });
};

I'm struggling with making it single select though. It's easy to return new Map with false values anytime cell is tapped, but that means the cell cannot be deselected by another tap on it, which is the desired feature in my case.

onPressItem = (id) => {
  this.setState((state) => {
    const selected = new Map();
    selected.set(id, !selected.get(id)); 
    return { selected };
  });
};

How would you implement it? Should I use lodash to iterate over the Map to find the one that already is true and change its value (now sure how to iterate over Map though), or maybe there is some better approach I am missing right now?

EDIT

Iterating over elements of the selected Map seems to be a really ugly idea, but it is simple and it actually works. Is there any better way to do it that I am missing out on?

onPressItem = (id: string) => {
  this.setState((state) => {
    const selected = new Map(state.selected);
    selected.set(id, !selected.get(id));
    for (const key of selected.keys()) {
      if (key !== id) {
        selected.set(key, false);  
      } 
    }
    return { selected };
  });
 };

Thanks in advance

Upvotes: 4

Views: 1290

Answers (2)

josecastillo86
josecastillo86

Reputation: 330

I had the same issue, my solution was:

_onPressItem = (id: string) => {
        // updater functions are preferred for transactional updates
        this.setState((state) => {
            // copy the map rather than modifying state.
            const selected = new Map(state.selected);

            // save selected value
            let isSelected = selected.get(id);

            // reset all to false
            selected.forEach((value, key) => {
                selected.set(key, false);
            });

            // then only activate the selected
            selected.set(id, !isSelected);

            return { selected };
        });
    };

Upvotes: 0

Sofiane Daoud
Sofiane Daoud

Reputation: 888

You can just set only one value instead of a map like this

onPressItem = (id) => {
  this.setState((state) => {
    const selected = selected === id ? null : id; 
    return { selected };
  });
};

Upvotes: 4

Related Questions