Pets Front-End Delete
Learning Objective: By the end of this lesson, students will be able to implement delete functionality in a React application, enabling them to make delete requests to an API and remove items from the user interface dynamically.
Delete a pet
In this section, we’ll build the delete functionality. Let’s review the requirements laid out in the intro:
- Add a button to delete a pet.
- Remove the pet from the UI.
And translate them into a user story:
👤 As a user, I want to be able to click a button on the details view to delete a pet.
🎓 You Do: Implement delete functionality
Take some time to complete the following steps by following the instructions below and cross-referencing them with your existing code as needed.
-
Handle the delete button click event.
- In the
Appcomponent (where ourpetsstate is), create a new function calledhandleDeletePet()to handle the deletion of a pet. This function will eventually invoke a service function and update thepetsstate.- This function should accept the
_idof the pet as an argument. - Pass
handleDeletePetas a prop to thePetDetailcomponent.
- This function should accept the
- In the
PetDetailcomponent:- Add a new button inside the same
divas the Edit Pet button. The new button should have the text Delete Pet. - Make the button call the
handleDeletePet()function when clicked, passing the_idof the selected pet.
- Add a new button inside the same
- In the
-
Get the
_idto the service.- Inside of
petService.js:- Create a new function called
deletePet(). This function should accept a pet’s_idas an argument. - Export the function.
- Create a new function called
- In the
Appcomponent’shandleDeletePet()function:- Call the new
deletePet()service and pass it the pet’s_id. - Assign the response to a variable called
deletedPet. - Console log the
deletedPetobject (right now, it will logundefined).
- Call the new
- Inside of
-
Make the request to the back-end and process the response.
- Return to the
deletePet()function inpetService.jsand complete the function:- Use a
try...catchblock to handle any errors. - Use
fetchto make aDELETErequest to the base URL with the_idof the pet (check your server code if you need clarity on the exact URL). - Use the
json()method to parse the response. - Return the parsed response.
- Use a
- If you test this now, you should see the delete pet object logged to the console (because of the
console.log(deletedPet)inhandleDeletePet()in theAppcomponent).
- Return to the
-
Update the
petsstate.- In the
Appcomponent’shandleDeletePet()function:- Use the array’s
filter()method to remove the deleted pet frompetsstate. - This function should set the
selectedstate tonulland theisFormOpenstate tofalse. - If
deletedPethas an error, throw a newErrorand log the error. Use atry...catchblock to handle this.
- Use the array’s
- In the
Test it out in the browser and make sure you can update a pet and see it displayed in the UI.
Check your work
Step 1
// src/components/PetDetail/PetDetail.jsx
const PetDetail = (props) => {
if (!props.selected) {
return (
<div>
<h1>NO DETAILS</h1>
</div>
);
}
return (
<div>
<h1>{props.selected.name}</h1>
<h2>Breed: {props.selected.breed}</h2>
<h2>
Age: {props.selected.age} year{props.selected.age > 1 ? 's' : ''} old
</h2>
<div>
<button onClick={() => props.handleFormView(props.selected)}>
Edit Pet
</button>
<button onClick={() => props.handleDeletePet(props.selected._id)}>
Delete Pet
</button>
</div>
</div>
);
};
export default PetDetail;
// src/services/petService.js
const deletePet = async (petId) => {
try {
const res = await fetch(`${BASE_URL}/${petId}`, {
method: 'DELETE',
});
return res.json();
} catch (err) {
console.log(err);
}
};
// src/App.jsx
import { useState, useEffect } from 'react';
import * as petService from './services/petService';
import PetList from './components/PetList/PetList';
import PetDetail from './components/PetDetail/PetDetail';
import PetForm from './components/PetForm/PetForm';
function App() {
const [pets, setPets] = useState([]);
const [selected, setSelected] = useState(null);
const [isFormOpen, setIsFormOpen] = useState(false);
useEffect(() => {
const fetchPets = async () => {
try {
const fetchedPets = await petService.index();
if (fetchedPets.err) {
throw new Error(fetchedPets.err);
}
setPets(fetchedPets);
} catch (err) {
console.log(err);
}
};
fetchPets();
}, []);
const handleSelect = (pet) => {
setSelected(pet);
setIsFormOpen(false);
};
const handleFormView = (pet) => {
if (!pet._id) setSelected(null);
setIsFormOpen(!isFormOpen);
};
const handleAddPet = async (formData) => {
try {
const newPet = await petService.create(formData);
if (newPet.err) {
throw new Error(newPet.err);
}
setPets([newPet, ...pets]);
setIsFormOpen(false);
} catch (err) {
console.log(err);
}
};
const handleUpdatePet = async (formData, petId) => {
try {
const updatedPet = await petService.update(formData, petId);
if (updatedPet.err) {
throw new Error(updatedPet.err);
}
const updatedPetList = pets.map((pet) => (
pet._id !== updatedPet._id ? pet : updatedPet
));
setPets(updatedPetList);
setSelected(updatedPet);
setIsFormOpen(false);
} catch (err) {
console.log(err);
}
};
const handleDeletePet = async (petId) => {
try {
const deletedPet = await petService.deletePet(petId);
if (deletedPet.err) {
throw new Error(deletedPet.err);
}
setPets(pets.filter((pet) => pet._id !== deletedPet._id));
setSelected(null);
setIsFormOpen(false);
} catch (err) {
console.log(err);
}
};
return (
<>
<PetList
pets={pets}
handleSelect={handleSelect}
handleFormView={handleFormView}
isFormOpen={isFormOpen}
/>
{isFormOpen ? (
<PetForm
handleAddPet={handleAddPet}
selected={selected}
handleUpdatePet={handleUpdatePet}
/>
) : (
<PetDetail
selected={selected}
handleFormView={handleFormView}
handleDeletePet={handleDeletePet}
/>
)}
</>
);
}
export default App;
Congratulations! 🎉
You’ve successfully completed a full-stack project featuring a React front-end and an Express API back-end, which together are capable of performing complete CRUD operations on a resource while providing a UI to elevate the user experience. This is a significant achievement in your learning journey!
Well done building your first MERN (MongoDB, Express, React, and Node.js) stack project! This milestone sets a solid foundation for your future projects and development skills. Keep up the great work!