in my react native app I have a list of tags where people can choose from, they click on an item and add it to the list of array of item ids, if they click over an item which id is already in the array, I want to remove it from array.
Right now all I can do is add ids to array, I can't remove it if already present.
PD: I also check if list of ids is lower than 10. Also, is there a cleanest way to write the function?
const [selectedItems, setSelectedItems] = useState([]);
const toggleItem = useCallback((itemId) =>
{
setSelectedItems(prev => prev.includes(itemId) ? prev.filter(obj => obj.id != itemId) : prev.length < 10 ? [ ...prev, itemId] : prev);
},[])
CodePudding user response:
It looks like you're mixing and matching the items in the array - is it a list of IDs, or the list of objects?
prev.includes(itemId) // This looks like a list of IDs
? prev.filter(obj => obj.id != itemId) // This looks like a list of objects
In terms of "a cleaner way to write the function" - you can be a bit more efficient if you don't do the includes
check first, as that involves an extra iteration over your items. In the example below I've changed the callback function to assume it gets passed the whole item, instead of just the id:
const [selectedItems, setSelectedItems] = useState([]);
const toggleItem = item => setSelectedItems(prev => {
const next = prev.filter(selectedItem => selectedItem.id !== item.id);
// The item wasn't removed from the list so it needs to be added
if (next.length === prev.length && next.length < 10) {
next.push(item);
}
return next;
});
You could also consider using a Map instead of an array:
const [selectedItems, setSelectedItems] = useState(new Map());
const toggleItem = item => setSelectedItems(prev => {
const next = new Map(prev);
if (!next.delete(item.id) && next.size < 10) {
next.set(item.id, item);
}
});
// If you need the items as an array
const selectedItemsArray = Array.from(selectedItems.values());
Finally - I'd also remove the useCallback
because you probably don't need it.
CodePudding user response:
This might be right for you:
if (selectedItems.indexOf(itemId) > -1) {
setSelectedItems(selectedItems.filter(obj => obj.id != itemId))
} else if (selectedItems.length < 10) {
setSelectedItems([ ...selectedItems, itemId])
}
// or
if (selectedItems.indexOf(itemId) > -1) {
setSelectedItems(selectedItems.filter(obj => obj.id != itemId))
return
}
if (selectedItems.length < 10) {
setSelectedItems([ ...selectedItems, itemId])
}