[SOLVED] How can I disable multiple select in react map

Issue

This Content is from Stack Overflow. Question asked by Julia Schafer

When I click the white background button I just want to give yellow background to the selected/pressed button. but for now, I can select more than one button. how can I disable multiple selections?

enter image description here

Common > AddressButton.tsx

    const handlePress = () => {
        setAddressData(addressData);
        if (ratesData) setRatesData(null);
        if (selectedRate) setSelectedRate(null);
        setSelectedItem(!selectedItem)
    };

        const [selectedItem, setSelectedItem] = useState<boolean>(false);

    return (
        <HomeAddressContainer isSelected={selectedItem}>
            <Pressable onPress={handlePress}>
            <HomeAddressRow>
                <HomeAddressIcon>
                <SVGCustomIcon name={selectedItem ? "HomeAddressIcon" : "HomeIconWhite"} />
                    <HomeAddressTitle>{name}</HomeAddressTitle>
                    <HomeAddressName>{company}</HomeAddressName>
                    <HomeAddressStreet>{street1}</HomeAddressStreet>
                    <HomeAddressStreet>{city}, {zip}, {country}</HomeAddressStreet>
            
        </HomeAddressContainer>
    );
};

style.ts for AddressButton.tsx

interface HomeAddressProps {
    isSelected: boolean;
}

export const HomeAddressContainer = styled.View<HomeAddressProps>`
    width: 219px;
    height: 94px;
    border-radius: 8px;
    background-color: #ffffff;
    ${props => props.isSelected && 'background-color: #f9b300'};

`;

Components > Addresses.tsx

  const handlePress = (rate: any, index: number) => {
        setSelectedItem(index);
        // selectRate(rate);
        setSelectedRate(rate);
    };

{addressesList.map((address: AddressData, index) => (
                  <Pressable
                            key={index}
                            onPress={() => handlePress(address, index)}>
                <HomeAddress
                    key={index}
                    addressData={address}
                    packageId={packageId}
                    isSelected={index === selectedItem}
                />
                </Pressable>
            ))}



Solution

Ok, so first thing to do: add isSelected extraction from Props in HomeAddress component, remove 1 useState from inside of it and change TSX to respect the isSelected passed from outside.

// change
const HomeAddress = ({ addressData, packageId, isSelected }: Props)

// remove
const [selectedItem, setSelectedItem] = useState<boolean>(false);

// change
<HomeAddressContainer isSelected={isSelected}>

// change
<SVGCustomIcon name={isSelected ? "HomeAddressIcon" : "HomeIconWhite"} />

Next – in your SavedAddresses component – change the handlePress a bit to respect setting and unsetting the active item index:

const handlePress = (rate: any, index: number) => {
  setSelectedItem((curr) => {
    // if curr value === passed index - we need to unset this selectedItem
    const toUnset = curr === index;
    // and unset the selectedRate
    setSelectedRate(toUnset ? null : rate);
    return toUnset ? null : index;
  });
};

So now setSelectedItem will check the currently selected item index and if it match with one that passed from parameter – it will set it to null.

Please, try and tell me if there is any more issues with that logic.

(Honestly, your code needs a good refactoring in terms of state management)


This Question was asked in StackOverflow by Julia Schafer and Answered by Sergey Sosunov It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?