Unable to remove speific card component in a loop

39 Views Asked by At
    const MealBox = ({ mealTime, setShowBox }: { mealTime: string; setShowBox: any }) => {
    const [meal, setMeal] = useState("Jollof rice")
    
    // console.log('meal', meal)
    
    return (
        <Box border={'1px solid #f0eeeb'} rounded={'lg'} p="10px">
            <Flex
                alignItems={'center'}
                gap={'25px'}
                w={'270px'}
                justifyContent={'space-between'}
            >
                <Box w='full'>
                    <Flex justify={'space-between'}>
                        <Text fontWeight={'semibold'}>{mealTime}</Text>
                        <MdOutlineRefresh size={24} />
                    </Flex>
                    <Select onChange={(e) => setMeal(e.target.value)} value={meal}>
                        <option value="Jollof rice">Jollof Rice</option>
                        <option value="Spaghetti">Spaghet

ti</option>
                </Select>
            </Box>
        </Flex>

        <Box bg={'#f8f8f7'} p="10px" mt="15px" rounded={'lg'}>
            <Flex alignItems={'center'} justifyContent={'space-between'}>
                <Text fontWeight={'semibold'}>{meal}</Text>
                <Box onClick={() => setShowBox(false)} cursor={'pointer'}>
                    <LiaTimesSolid />
                </Box>
            </Flex>
            <Text>Chicken Republic - Gbagada</Text>
            <Text fontWeight={'medium'}>NGN 2,500</Text>
            <Flex alignItems={'center'} gap={'15px'} mt={'10px'}>
                <Text>Sides:</Text>
                <Select>
                    <option value="Youghurt">Youghurt</option>
                    <option value="Orange juice">Orange juice</option>
                </Select>
            </Flex>
            <Flex alignItems={'center'} gap={'15px'} mt={'10px'}>
                <Text>Extras:</Text>
                <Select>
                    <option value="Youghurt">Plantain</option>
                    <option value="Orange juice">Coleslaw</option>
                </Select>
            </Flex>
        </Box>
    </Box>
);

The code above is a card component that has a cancel icon which is meant to remove the card when clicked on.

    const [showBreakfastBox, setShowBreakfastBox] = useState(true);
const [showLunchBox, setShowLunchBox] = useState(true);
const [showDinnerBox, setShowDinnerBox] = useState(true);

These usestate variables are used to render conditionally whether the mealbox component is shown or addfood component is shown -

{Array(7)
            .fill(0)
            .map((item, idx) => {


                const tomorrow = new Date(currentDate)
                tomorrow.setDate(currentDate.getDate() + idx + 1);

                const formattedDate = tomorrow.toLocaleDateString('en-US', { month: 'long', day: 'numeric' });

                const dayOfWeek = tomorrow.toLocaleDateString('en-US', { weekday: 'long' })

                return (
                    <Box
                        key={idx}
                        overflowX={'scroll'}
                        sx={{
                            '::-webkit-scrollbar': {
                                display: 'none',
                            },
                        }}
                        maxW={'1420px'}
                        w={'1420px'}
                        my={'25px'}
                        mx="auto"
                    >
                        <Flex gap={'15px'} width={(10 * 270).toString() + 'px'}>
                            <Box w={'170px'}>
                                <Text>{formattedDate}</Text>
                                <Text fontWeight={'semibold'}>{dayOfWeek}</Text>
                                <Text fontSize={'.875rem'} color='#AA9F93'>1669 Calories</Text>
                                <Box mt='10px'>
                                    <MdOutlineRefresh size={24} />
                                </Box>
                            </Box>

                            {
                                showBreakfastBox
                                    ? <MealBox mealTime={'Breakfast'} setShowBox={setShowBreakfastBox} />
                                    : <AddFood mealTime={'Breakfast'} setShowBox={setShowBreakfastBox} />
                            }
                            {
                                showLunchBox
                                    ? <MealBox mealTime={'Lunch'} setShowBox={setShowLunchBox} />
                                    : <AddFood mealTime={'Lunch'} setShowBox={setShowLunchBox} />
                            }
                            {
                                showDinnerBox
                                    ? <MealBox mealTime={'Dinner'} setShowBox={setShowDinnerBox} />
                                    : <AddFood mealTime={'Dinner'} setShowBox={setShowDinnerBox} />
                            }
                            
                            <SnackBox />
                        </Flex>
                    </Box>
                );
            })}

And in this code I am rendering the mealbox component on the screen and using those usestate variables declared earlier to conditionally render it with addfood component but the issue I am facing now is because of this loop whenever I click the cancel button, all the 7 card component leaves the screen and the goal is to make just one component leave the screen. I would appreciate every form of help I can get to solve this issue.

2

There are 2 best solutions below

0
Olaoluwa Anigboro-Napoleon On

I have figured it out. So I figured I shouldn't remove the mealbox card inside the loop so I created a new component and did the conditional rendering in the component plus the card removal too in the component and I rendered the new component inside the loop.

    const CheckLoop = ({mealTime}: {mealTime: string}) => {
    const [showInitialBox, setShowInitialBox] = useState(true);
    
    return (
        showInitialBox
            ? <MealBox mealTime={mealTime} setShowBox={setShowInitialBox} />
            : <AddFood mealTime={mealTime} setShowBox={setShowInitialBox} />
    )
}

I did some thing like this and put Checkloop component inside the array.map

1
Hashan Hemachandra On

The behavior you're experiencing occurs because the showBreakfastBox, showLunchBox, and showDinnerBox states are shared across all seven instances of the daily meals. When any of them is set to false, it affects all seven days since they're all referencing the same state variable.

To solve this, you need to maintain separate states for each day. One way to do this is by using an array of objects where each object represents the state of a single day.

const [days, setDays] = useState(Array(7).fill().map(() => ({
    showBreakfastBox: true,
    showLunchBox: true,
    showDinnerBox: true
})));

Now, you need to modify the rendering logic to use the state of the specific day.

{days.map((day, idx) => {
    // ...your existing code to calculate tomorrow, formattedDate, and dayOfWeek

    const setShowBox = (meal, show) => {
        setDays(currentDays => {
            const newDays = [...currentDays];
            newDays[idx] = {
                ...newDays[idx],
                [meal]: show
            };
            return newDays;
        });
    };

    return (
        <Box key={idx} /* ...rest of your props */>
            <Flex /* ...rest of your props */>
                {/* ...rest of your components */}
                {
                    day.showBreakfastBox
                        ? <MealBox mealTime={'Breakfast'} setShowBox={(show) => setShowBox('showBreakfastBox', show)} />
                        : <AddFood mealTime={'Breakfast'} setShowBox={(show) => setShowBox('showBreakfastBox', show)} />
                }
                {
                    day.showLunchBox
                        ? <MealBox mealTime={'Lunch'} setShowBox={(show) => setShowBox('showLunchBox', show)} />
                        : <AddFood mealTime={'Lunch'} setShowBox={(show) => setShowBox('showLunchBox', show)} />
                }
                {
                    day.showDinnerBox
                        ? <MealBox mealTime={'Dinner'} setShowBox={(show) => setShowBox('showDinnerBox', show)} />
                        : <AddFood mealTime={'Dinner'} setShowBox={(show) => setShowBox('showDinnerBox', show)} />
                }
                {/* ...rest of your components */}
            </Flex>
        </Box>
    );
})}