Search code examples
javascriptreactjsformsreact-forms

how do i stop users from submitting the same form on react


I've got a website site I'm building with a form that I built.

Here is the code:

import React, { useState } from "react";

const Form = () => {
  const [formData, setFormData] = useState({});
  const [message, setMessage] = useState("");

  const handleInput = (e) => {
    const copyFormData = { ...formData };
    copyFormData[e.target.name] = e.target.value;
    setFormData(copyFormData);
  };

  const sendData = async (e) => {
    e.preventDefault();

    const { name, email, message } = formData;
    try {
      const response = await fetch(
        "MYKEY",

        {
          method: "post",
          body: JSON.stringify([[name, email, message]]),
          headers: {
            "Content-Type": "application/json",
          },
        }
      );

      const json = await response.json();
      console.log("Success", JSON.stringify(json));
      setMessage("Thanks for subscribing!");
    } catch (error) {
      console.error("Error:", error);
      setMessage("There seems to be a problem");
    }
  };

  return (
    <div className=" p-3 w-full md:p-24">
      <form
        className="w-full border-solid border-black border-4 items-center"
        id="contact"
        name="contact"
        required
        onSubmit={sendData}
      >
        <div className="text-center mt-4 mb-5">
          <h2 className="font-semibold text-4xl mb-2 md:mt-10 md:text-6xl md:mb-4">
            newsletter
          </h2>
          <p className="text-gray-500 md:text-2xl">lets stay connected</p>
        </div>

        <div className="flex flex-wrap flex-col md:justify-center md:flex-row p-2">
          <input
            className="bg-gray-100 mb-4 h-10 w-full  p-4 text-gray-500 md:w-1/5 md:mx-3 md:h-14"
            name="name"
            type="text"
            placeholder="name"
            required
            onChange={handleInput}
          ></input>

          <input
            className="bg-gray-100 mb-4 h-10 w-full  p-4 text-gray-500 md:w-2/5 md:mx-3 md:h-14"
            name="email"
            type="email"
            placeholder="email"
            required
            onChange={handleInput}
          ></input>
          <input
            className="bg-blue-600 font-semibold tracking-wider mb-4 h-12 w-full text-white justify-center items-center md:h-14 md:w-1/6 md:mx-3"
            name="subscribe"
            type="submit"
            value="subscribe"
          ></input>
          <div className="font-semibold tracking-wider mb-4 text-black text-center justify-center items-center">
            {message}
          </div>
        </div>
      </form>
    </div>
  );
};

However, when a user submits the form they are able to keep pressing the subscribe button which leaves me with quite a few submissions.

How do I stop people from resubmitting? and only submitting once.

I thought having preventDefault would stop this from happening but still cant find a solution.

Thanks in advance!


Solution

  • This could be fleshed out more but you get the idea. Have a state that changes while you are submitting the data.

    import React, { useState } from "react";
    
    const Form = () => {
      const [formData, setFormData] = useState({});
      const [message, setMessage] = useState("");
      const [loading, setLoading] = useState("idle");
    
      const handleInput = (e) => {
        const copyFormData = { ...formData };
        copyFormData[e.target.name] = e.target.value;
        setFormData(copyFormData);
      };
    
      const sendData = async (e) => {
        e.preventDefault();
        setLoading("loading");
        const { name, email, message } = formData;
        try {
          const response = await fetch(
            "MYKEY",
            {
              method: "post",
              body: JSON.stringify([[name, email, message]]),
              headers: {
                "Content-Type": "application/json",
              },
            }
          );
    
          const json = await response.json();
          console.log("Success", JSON.stringify(json));
          setLoading("submitted");
          setMessage("Thanks for subscribing!");
        } catch (error) {
          console.error("Error:", error);
          setMessage("There seems to be a problem");
          setLoading("idle");
        }
      };
    
      return (
        <div className=" p-3 w-full md:p-24">
          <form
            className="w-full border-solid border-black border-4 items-center"
            id="contact"
            name="contact"
            required
            onSubmit={sendData}
          >
            <div className="text-center mt-4 mb-5">
              <h2 className="font-semibold text-4xl mb-2 md:mt-10 md:text-6xl md:mb-4">
                newsletter
              </h2>
              <p className="text-gray-500 md:text-2xl">lets stay connected</p>
            </div>
    
            <div className="flex flex-wrap flex-col md:justify-center md:flex-row p-2">
              <input
                className="bg-gray-100 mb-4 h-10 w-full  p-4 text-gray-500 md:w-1/5 md:mx-3 md:h-14"
                name="name"
                type="text"
                placeholder="name"
                required
                onChange={handleInput}
              ></input>
    
              <input
                className="bg-gray-100 mb-4 h-10 w-full  p-4 text-gray-500 md:w-2/5 md:mx-3 md:h-14"
                name="email"
                type="email"
                placeholder="email"
                required
                onChange={handleInput}
              ></input>
              {loading === "idle" &&
                <input
                className="bg-blue-600 font-semibold tracking-wider mb-4 h-12 w-full text-white justify-center items-center md:h-14 md:w-1/6 md:mx-3"
                name="subscribe"
                type="submit"
                value="subscribe"
              ></input>
              }
            
              <div className="font-semibold tracking-wider mb-4 text-black text-center justify-center items-center">
                {message}
              </div>
            </div>
          </form>
        </div>
      );
    };