I am creating a flashcard app in React using hooks and having trouble deleting a deck of flashcards. I am able to render Bootstrap cards on the page with the flashcards name, description, card count, and the buttons as desired. However, I am unable to delete a deck of cards as I'm being told setFlashcards is not a function. Here is my code:
App.js
function Layout() {
const [flashcards, setFlashcards] = useState([])
useEffect(() => {
axios
.get('http://localhost:5000/decks?_embed=cards')
.then(res => {
setFlashcards(res.data.map((questionItem, index) => {
return {
id: `${index}-${Date.now()}`,
name: questionItem.name,
description: questionItem.description,
cards: questionItem.cards.length,
}
}))
})
}, [])
return (
<div>
<Header />
<ShowAllDecks flashcards={flashcards} setFlashcards={setFlashcards} />
<NotFound />
</div>
)
}
ShowAllDecks.js
function ShowAllDecks({ flashcards, setFlashcards }) {
return (
<div className='container'>
<button>Create New</button>
{flashcards.map((flashcard) => {
return <Deck flashcards={flashcards} flashcard={flashcard} key={flashcard.id} />
})}
</div>
)
}
Deck.js
function Deck({ flashcard, flashcards, setFlashcards }) {
const deleteHandler = () => {
setFlashcards(flashcards.filter(el => el.id !== flashcard.id))
}
return (
<div className='container'>
<div className='card'>
<div className='card-body'>
<h3 className='card-title'>{flashcard.name}</h3>
<p className='card-text'>{flashcard.description}</p>
<p className='card-text'>{flashcard.cards} cards</p>
<button>View</button>
<button>Study</button>
<button onClick={deleteHandler}>Delete</button>
</div>
</div>
</div>
)
}
Example of a deck with one card:
[
{
'id': 1,
'name': 'A Deck Name'
'description': 'A Deck Description',
'cards': [
{
'id': 1,
'front': 'Front of card',
'back': 'Back of card',
'deckId': 1
}
]
}
]
setFlashcardstoDeckLayoutwhere the state is, you should keep the delete handler in the same component with the state and pass a reference to the delete handler on to children. The delete handler should consume an "id"/index of the data element to remove from state. The delete handler should also use a functional update so you don't need to also pass the state object around either.<button onClick={() => deleteHandler}>Delete</button>deleteHandler. OP's code is fine there though.deleteHandleris inside the deck itself, and the deck itself has access to theflashcardsarray, the singleflashcardbeing rendered, and thesetFlashcardshook (although I've never passed this through props so no idea if there would be any problems with it). If it's not written in an arrow function wouldn't it be called on render? But I agree the delete function should be in theApp.jsand then take an id, then passed down to the component. Then can pass the id through to that as you say, and thesetFlashcardscan run inApp.js, don't have to pass so much down.