This article is a continuation of the article I wrote on the RLS policy issue I solved with Supabase.
After I had fixed the RLS policy issue, I discovered that the way I structured my code was wrong. Semantically, it looked sort of correct but it was logically wrong. Here's a live preview of the project so you get what I mean.
When a user clicks the "Join early access" button, a function called subscribeEmail() is fired. This initially didn't look like a problem as I only considered the fact that users will be clicking the button once when they want to sign up for the waitlist, I didn't take into account that users could click the button multiple times (This could have been avoided if I disable the button once they click on it), but even though I were to disable the button, if the user clicks on the button again after the disabled property is removed, I will still encounter the same issue.
Here's the code:
"use client";
import { useState } from "react";
import { subscribeEmail } from "@/lib/supabase";
export default function WaitList() {
const [email, setEmail] = useState("");
const [status, setStatus] = useState<
"idle" | "loading" | "success" | "error"
>("idle");
const handleSubmit = async (e: React.SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
setStatus("loading");
const { error } = await subscribeEmail(email);
if (error) {
setStatus("error");
} else {
setStatus("success");
setEmail("");
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email address"
required
/>
<button
type="submit"
disabled={status === "loading"}
>
{status === "loading" ? "Joining..." : "Get Early Access"}
</button>
</form>
);
Doing it this way makes it unavoidable to keep calling subScribeEmail() when the button is clicked as all the logic is tied to that function. Calling this function will mean the user keeps trying to add themselves to the db, even though they might already be added, before attempting to send them a confirmation email. What I was looking to accomplish is resending the user a confirmation email only when it fails.
To solve this problem, I rewrote the entire logic for the waitlist functionality. First of all, when the user enters their email and clicks the "Join early access" button, I first check if their email already exists. If it does, that means they have been added to the waitlist, else, they haven't yet joined
import {
getUserEmail,
subscribeEmail,
updateEmailStatus,
} from "@/lib/supabase";
import { sendConfirmationEmail } from "@/utils";
const handleSubmit = async (e: React.SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
setStatus("loading");
const { data, error } = await getUserEmail(email);
if (data.length === 0) {
// User has not been added to the waitlist
const { error } = await subscribeEmail(email);
if (error) {
setStatus("error");
toast.error(error);
return false;
}
setStatus("success");
setEmail("");
return true;
}
// If it reaches here, then they have been added
const { error: emailConfirmationError } = await sendConfirmationEmail(email);
if (emailConfirmationError) {
setStatus("error");
return false;
}
const { error: emailStatusError } = await updateEmailStatus(
email,
"delivered",
);
if (emailStatusError) {
setStatus("error");
return false;
}
setStatus("success");
setEmail("");
};
This way, I am able to know the state of the user, whether they have been added or not, and know which code to execute. There is one last scenario to consider here, what if the user has been added to the db and a confirmation email was sent to them but they still submit the form?. To combat that issue, I simply display a message indicating that they have already been added to the DB, and the confirmation email has been sent to them.
Solving this problem made me realize the importance of thinking through the problem you are trying to solve before writing any line of code. Being able to understand what you are trying to do is more important than just opening your editor to write code. Once you understand the problem you are trying to solve and do some research on it, you will definitely arrive at a solution.
Top comments (0)