Reputation: 385
I'm currently using SWR to fetch my data for client components in a NextJS project. I was looking for the most optimal way to write the function as I feel like my solution is a little hacky and I'm struggling with implementing the docs solution.
What I currently have is a route that returns user data.
A custom useUser hook that looks like this:
import axios from "axios";
import useSWR from "swr";
const useUser = () => {
// url
const url = `http://localhost:3000/api/user`;
// fetcher
const fetcher = (url) => axios.get(url).then((res) => res.data);
// swr
const { data, error, isLoading, mutate } = useSWR(url, fetcher);
return {
user: data,
loading: isLoading,
error,
mutate,
};
};
export default useUser;
Then I implement in a page like so:
import useUser from "@/utils/hooks/useUser";
import {useState} from "react";
const Dashboard = () => {
// state
const [modalOpen, setModalOpen] = useState(false);
const [id, setId] = useState(null);
// swr destructure
const { user, loading, error, mutate } = useUser();
return (
<div>
<h1>Dashboard</h1>
<button
onClick={async () => {
// mutate local data
mutate(
(data) => {
return {
...data,
quizzes: data.quizzes.filter((quiz) => quiz.id !== id),
};
},
{
revalidate: false,
}
);
// ui responsive, close modal on delete
setModalOpen(false);
try {
// delete quiz on the backend
await fetch(`http://localhost:3000/api/quiz?quizId=${id}`, {
method: "DELETE",
});
// revalidate the data coming from the useUser hook
await mutate();
} catch (e) {
console.log(e);
} finally {
setId(null);
}
}}
>Delete</button>
</div>
)
}
Anyone have a better suggestion?
As I've mentioned above.
Upvotes: 0
Views: 1485
Reputation: 34
In your Dashboard component, when you delete a quiz, you're locally updating the data via mutate, then making a backend request to delete the quiz, and finally revalidating the data with mutate(). However, it seems like you're not passing the updated data to mutate after the deletion.
One way to address this issue is by providing the new data to mutate after deleting the quiz. Here's an updated version:
const Dashboard = () => {
const [modalOpen, setModalOpen] = useState(false);
const [id, setId] = useState(null);
const { user, loading, error, mutate } = useUser();
const handleDelete = async () => {
try {
// Delete quiz on the backend
await fetch(`http://localhost:3000/api/quiz?quizId=${id}`, {
method: "DELETE",
});
// Filter quizzes locally
const updatedQuizzes = user.quizzes.filter((quiz) => quiz.id !== id);
// Update the local data by providing the new data to mutate
mutate({ ...user, quizzes: updatedQuizzes }, false);
setModalOpen(false); // Close modal
setId(null);
} catch (e) {
console.log(e);
}
};
return (
<div>
<h1>Dashboard</h1>
<button onClick={handleDelete}>Delete</button>
</div>
);
};
This code simplifies the deletion process by filtering the quizzes locally, then updating the data with mutate. This way, you're passing the updated data to mutate after the deletion, avoiding the need to revalidate the entire data set from the server.
Upvotes: 0