reactjsarraysreact-hooksarray-map

usestate variable increments when I click on a different increment button


so I am declaring a usestate variable as "count" and I am mapping through a list of 2 items. This code shows the variable declaration and the function to increment and decrement

const [count, setCount] = useState(1);
const increment = () => {
  setCount((prev) => prev + 1);
};

const decrement = () => {
  setCount((prev) => {
    if (prev == 1) return prev;
    return prev - 1;
  });
};

And the next code shows how I am mapping through an item and displaying a text that holds the count variable

{
   cartItemArr.map((entry: any, index: number) => {
      return (

        <Flex
          key={index}
          w={'100%'}
          alignItems={'center'}
          justifyContent={'space-between'}
        >
           <Flex direction={'column'} justifyContent={'space-between'}>
             <Text fontWeight={600} fontSize={'14px'} textColor={'#000'}>
               {entry?.foodId.nameOfFood}
             </Text>
             <Text fontWeight={400} fontSize={'12px'} textColor={'#000'}>
               #{entry?.foodId.pricePerServing}
             </Text>
           </Flex>
           <HStack
             justify={'center'}
             w="109px"
             borderRadius={'40px'}
             py="8px"
             border={'1px solid #AA9F93'}
           >
             <AiOutlineMinus cursor={'pointer'} onClick={decrement} className='cursor-pointer' />
             <Text>{count}</Text>
             <AiOutlinePlus cursor={'pointer'} onClick={increment} className='cursor-pointer' />
          </HStack>
        </Flex>
       )
      })
      }

So when I click on the first item, the second item also increases. I know that it is because both of them have the count variable which is why it is behaving like that, is there something I can do that will make the counts not affect each other on the mapped items? I hope I can communicate my issue well. For better context, this is the screen I am building; enter image description here


Solution

  • Create a separate React component for the individual entries, something like this:

    const Entry = ({ entry }: { entry: any }) => {
      const [count, setCount] = useState(1);
      const increment = () => {
        setCount((prev) => prev + 1);
      };
    
      const decrement = () => {
        setCount((prev) => {
          if (prev == 1) return prev;
          return prev - 1;
        });
      };
      return (
        <Flex
          w="100%"
          alignItems="center"
          justifyContent="space-between"
        >
          <Flex direction="column" justifyContent="space-between">
            <Text fontWeight={600} fontSize="14px" textColor="#000">
              {entry?.foodId.nameOfFood}
            </Text>
            <Text fontWeight={400} fontSize="12px" textColor="#000">
              #{entry?.foodId.pricePerServing}
            </Text>
          </Flex>
          <HStack
            justify="center"
            w="109px"
            borderRadius="40px"
            py="8px"
            border="1px solid #AA9F93"
          >
            <AiOutlineMinus
              cursor="pointer"
              onClick={decrement}
              className="cursor-pointer"
            />
            <Text>{count}</Text>
            <AiOutlinePlus
              cursor="pointer"
              onClick={increment}
              className="cursor-pointer"
            />
          </HStack>
        </Flex>
      );
    };
    

    That way the count variable is local to each entry rather than to the entire cart.

    Then update your map to something like this:

          {cartItemArr.map((entry: any, index: number) => {
            return <Entry entry={entry} key={index} />;
          })}