Search code examples
reactjstypescriptevent-handlingcomponentsreact-props

Issues deleting from a React grandchild component


I am having issues using a handleDelete function that is passed down to a grandchild with all the necessary props.

The structure of my components can go either: Deck > CardSlider > Card or Deck > Card, depending on if the user is in grid or carousel view. When I call the handleDelete function from Deck -> Card component (grid view), I am able to successfully delete the card, however I can't delete when I go from Deck -> CardSlider -> Card in carousel view.

When I check the network in chrome devtools, it shows a 200 status code for DELETE, however it doesn't actually delete!

I'm completely stumped. Any ideas?

async function handleDeleteCard(cardId: number) {
    const newDeck = await deleteCard(deckId, cardId)
    setCards(newDeck.cards);        
}

return (
       <div className="deck">
          
          {view == 'grid' ? 

            <ul className="cards">
              {cards.map((card, cardId) => 
                <li key={cardId}>
                    <Card 
                      card={card}
                      cardBack={cardBack} 
                      cardFront={cardFront}
                      cardId={cardId} 
                      flippedCard={flippedCard} 
                      handleDeleteCard={handleDeleteCard} 
                      handleFlip={handleFlip} 
                      mode={mode}
                      view={view}
                    />
                </li>)}
            </ul> 
            :
            <CardSlider 
              cards={cards}
              cardBack={cardBack} 
              cardFront={cardFront} 
              flippedCard={flippedCard}  
              handleFlip={handleFlip} 
              handleDeleteCard={handleDeleteCard} 
              mode={mode} 
              view={view}
            />
          }
)

CardSlider component

Card component

I tried passing the Card component all the necessary props from the CardSlider component in order to delete the card in caroussel view. I get the proper card ID and deck ID when I log the card details to be deleted in the handleDelete function, however it doesn't actually get deleted


Solution

  • The issue is that you give cardId 2 different meanings:

    • In Deck > Card, cardId is the index of the card within the cards array:
    // cardId is the 2nd parameter of map callback,
    // i.e. the index in the array being mapped
    cards.map((card, cardId) =>
      <li key={cardId}>
        <Card 
          card={card}
          cardId={cardId} // Index
          handleDeleteCard={handleDeleteCard} 
          />
      </li>)
    
    • In Deck > CardSlider > Card, it is now the card._id property (ObjectId or string from MongoDB document?)
    <Card 
      card={cards[currentIndex]}
      cardId={cards[currentIndex]._id} // Document identifier, instead of index
    
      // handleDeleteCard={() => handleDeleteCard(cards[currentIndex]._id)}
    />
    

    When you monitor the DELETE request, you should see the difference in cardId argument.

    When I call the handleDelete function from Deck -> Card component (grid view), I am able to successfully delete the card, however I can't delete when I go from Deck -> CardSlider -> Card in carousel view.

    This means that your Backend knows only how to handle cardId as the card index within an array of cards, but not as the card._id field.

    While an immediate solution could be to bring consistency in cardId meaning by changing what CardSlider uses (I suspect that it loops in the same order over the cards array, so it should be able to generate the same index, very probably already as currentIndex):

    <Card 
      card={cards[currentIndex]}
      cardId={currentIndex} // Index, assuming it is in the same order as in cards array?
    
      handleDeleteCard={() => handleDeleteCard(currentIndex)}
    />
    

    ...a more robust solution would on the contrary change Deck and your Backend, so that they handle the actual card._id value (which is really a "cardId" and not just an "index").

    That way, you would be able to delete any arbitrary card in a deck, even if the cards array is shuffled for example.