The final step in completing the vehicle's CRUD operation is to implement the delete button functionality in the index view. This should be a quick and straightforward process.
- Extend the
src/hooks/useVehicle.jsx
hook.
Add a new destroyVehicle
function.
async function destroyVehicle(vehicle) { return axios.delete(`vehicles/${vehicle.id}`)}
And return it along with the other function in return statements.
return { vehicle: { data, setData, errors, loading }, createVehicle, updateVehicle, destroyVehicle,}
The whole src/hooks/useVehicle.jsx
file has the following content.
import { useState, useEffect } from 'react'import { useNavigate } from 'react-router-dom'import { route } from '@/routes' export function useVehicle(id = null) { const [errors, setErrors] = useState({}) const [loading, setLoading] = useState(false) const [data, setData] = useState({}) const navigate = useNavigate() useEffect(() => { if (id !== null) { const controller = new AbortController() getVehicle(id, { signal: controller.signal }) return () => controller.abort() } }, [id]) async function createVehicle(vehicle) { setLoading(true) setErrors({}) return axios.post('vehicles', vehicle) .then(() => navigate(route('vehicles.index'))) .catch(error => { if (error.response.status === 422) { setErrors(error.response.data.errors) } }) .finally(() => setLoading(false)) } async function getVehicle(id, { signal } = {}) { setLoading(true) return axios.get(`vehicles/${id}`, { signal }) .then(response => setData(response.data.data)) .catch(() => {}) .finally(() => setLoading(false)) } async function updateVehicle(vehicle) { setLoading(true) setErrors({}) return axios.put(`vehicles/${vehicle.id}`, vehicle) .then(() => navigate(route('vehicles.index'))) .catch(error => { if (error.response.status === 422) { setErrors(error.response.data.errors) } }) .finally(() => setLoading(false)) } async function destroyVehicle(vehicle) { return axios.delete(`vehicles/${vehicle.id}`) } return { vehicle: { data, setData, errors, loading }, createVehicle, updateVehicle, destroyVehicle, }}
- Extend the
src/hooks/useVehicles.jsx
hook by exposing thegetVehicles
function in the return statement, we need to call this function outside of the hook when we delete the vehicle record to re-fetch the list.
return { vehicles, getVehicles }
The whole src/hooks/useVehicles.jsx
file has the following content.
import { useState, useEffect } from 'react' export function useVehicles() { const [vehicles, setVehicles] = useState([]) useEffect(() => { const controller = new AbortController() getVehicles({ signal: controller.signal }) return () => { controller.abort() } }, []) async function getVehicles({ signal } = {}) { return axios.get('vehicles', { signal }) .then(response => setVehicles(response.data.data)) .catch(() => {}) } return { vehicles, getVehicles }}
- Update the
src/views/vehicles/VehiclesList.jsx
component as follows.
Import the useVehicle
hook and destructure return contents to have the destroyVehicle
function in scope.
import { useVehicle } from '@/hooks/useVehicle' // ... const { destroyVehicle } = useVehicle()
Do the same with the useVehicles
and getVehicles
functions.
const { vehicles, getVehicles } = useVehicles()
Now we can update the button itself.
From
<button type="button" className="btn text-white bg-red-600 hover:bg-red-500 text-sm">
To
<button type="button" className="btn text-white bg-red-600 hover:bg-red-500 text-sm" onClick={ async () => { await destroyVehicle(vehicle) await getVehicles() } }> X</button>
Here we just added an onClick
handler to the button. First, send a request to the server to delete a vehicle, and re-fetch the whole vehicles list.
The full src/views/vehicles/VehiclesList.jsx
file now should have the following content.
import { Link } from 'react-router-dom'import { route } from '@/routes'import { useVehicles } from '@/hooks/useVehicles'import { useVehicle } from '@/hooks/useVehicle' function VehiclesList() { const { vehicles, getVehicles } = useVehicles() const { destroyVehicle } = useVehicle() return ( <div className="flex flex-col mx-auto md:w-96 w-full"> <h1 className="heading">My Vehicles</h1> <Link to={ route('vehicles.create') } className="btn btn-primary"> Add Vehicle </Link> <div className="border-t h-[1px] my-6"></div> <div className="flex flex-col gap-2"> { vehicles.length > 0 && vehicles.map(vehicle => { return ( <div key={ vehicle.id } className="flex bg-gray-100 w-full p-2 justify-between" > <div className="flex items-center overflow-hidden w-full"> <div className="text-xl plate"> { vehicle.plate_number } </div> <div className="font-normal text-gray-600 pl-2 grow truncate"> { vehicle.description } </div> </div> <div className="flex gap-1"> <Link to={ route('vehicles.edit', { id: vehicle.id }) } className="btn btn-secondary text-sm" > Edit </Link> <button type="button" className="btn text-white bg-red-600 hover:bg-red-500 text-sm" onClick={ async () => { await destroyVehicle(vehicle) await getVehicles() } } > X </button> </div> </div> ) })} </div> </div> )} export default VehiclesList
Well done! You have successfully completed the implementation of full functionality for the user's vehicles. Now, let's move on to the next lesson and implement parking.
No comments yet…