Deleting Feedback

Now that users have a way to add sites/feedback, we need to allow them to manage this content. This will consist of two parts, deleting and editing.

💡

This section applies to both feedback and sites. The only real difference is the collection name.

First, let's create a function allowing us to delete feedback from the client-side. Given an ID, find the document inside the feedback collection and delete it.

lib/db.js

export function deleteFeedback(id) {
return firestore.collection('feedback').doc(id).delete();
}

Deleting feedback or sites is a crucial user action. To ensure they really want to delete, we can prompt a confirmation modal. Let's create the component for that, which is invoked by a button. We still complete onDelete next.

components/DeleteFeedbackButton.js

import React, { useState, useRef } from 'react';
import {
AlertDialog,
AlertDialogBody,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogContent,
AlertDialogOverlay,
IconButton,
Button
} from '@chakra-ui/core';
const DeleteFeedbackButton = ({ feedbackId }) => {
const [isOpen, setIsOpen] = useState();
const cancelRef = useRef();
const onClose = () => setIsOpen(false);
const onDelete = () => {
// TODO
onClose();
};
return (
<>
<IconButton
aria-label="Delete feedback"
icon="delete"
variant="ghost"
onClick={() => setIsOpen(true)}
/>
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={cancelRef}
onClose={onClose}
>
<AlertDialogOverlay />
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
Delete Feedback
</AlertDialogHeader>
<AlertDialogBody>
Are you sure? You can't undo this action afterwards.
</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose}>
Cancel
</Button>
<Button
fontWeight="bold"
variantColor="red"
onClick={onDelete}
ml={3}
>
Delete
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};
export default DeleteFeedbackButton;

Next, we need to update onDelete to call Firestore and delete the document.

components/DeleteFeedbackButton.js

import React, { useState, useRef } from 'react';
import { mutate } from 'swr';
import {
AlertDialog,
AlertDialogBody,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogContent,
AlertDialogOverlay,
IconButton,
Button
} from '@chakra-ui/core';
import { deleteFeedback } from '@/lib/db';
const DeleteFeedbackButton = ({ feedbackId }) => {
const [isOpen, setIsOpen] = useState();
const cancelRef = useRef();
const onClose = () => setIsOpen(false);
const onDelete = () => {
deleteFeedback(feedbackId);
onClose();
};
return (
<>
<IconButton
aria-label="Delete feedback"
icon="delete"
variant="ghost"
onClick={() => setIsOpen(true)}
/>
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={cancelRef}
onClose={onClose}
>
<AlertDialogOverlay />
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
Delete Feedback
</AlertDialogHeader>
<AlertDialogBody>
Are you sure? You can't undo this action afterwards.
</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose}>
Cancel
</Button>
<Button
fontWeight="bold"
variantColor="red"
onClick={onDelete}
ml={3}
>
Delete
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};
export default DeleteFeedbackButton;

Finally, this allows us to place an IconButton which will open the confirmation modal. We use the prop feedbackId to identify which document we want to delete.

// Somewhere in your codebase
<DeleteFeedbackButton feedbackId="BLspD6y8Bfn73LLm7nvW" />

As an exercise, determine where to place this component in the code.

Going Further

Since we've fetched the feedback with SWR and forwarded it to this page, we need to update the SWR cache when we delete so that the item is removed from the screen.

import { useAuth } from '@/lib/auth';
// ..
const auth = useAuth();
// ..
const onDelete = () => {
deleteFeedback(feedbackId);
mutate(
['/api/feedback', auth.user.token],
async (data) => {
return {
feedback: data.feedback.filter((feedback) => feedback.id !== feedbackId)
};
},
false
);
onClose();
};

This mutates the API call to fetch all feedback for a given user and filters out the deleted feedback based on its ID. Finally, it tells SWR not to revalidate by passing false as the second parameter.

You can view the API route to fetch feedback here.