Search code examples
reactjsnext.jsshadcnui

NextJs Form does not let me type into any of the inputs


I am developing a simple form to send messages to my email with the help of EmailJS. The EmailJS settings look fine, I tested them through the website and I got a 200 response.

This is my code:

"use client";

import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Textarea } from "./ui/textarea";
import { User, MailIcon, ArrowRightIcon, MessageSquare } from "lucide-react";
import emailjs from "@emailjs/browser";
import { ChangeEvent, FormEvent, useRef, useState } from "react";

const Form = () => {
  const formRef = useRef<HTMLFormElement>(null);
  const [form, setForm] = useState({
    name: "",
    email: "",
    message: "",
  });

  const handleChange = (
    e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
  ) => {
    const { name, value } = e.target;

    setForm({ ...form, [name]: value });
  };

  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    console.log("Dati del form:", form); // Verifica i dati del form nel log

    emailjs
      .send(
        "service_+++++",
        "template_++++++",
        {
          from_name: form.name,
          to_name: "Jhon Doe",
          from_email: form.email,
          to_email: "[email protected]",
          message: form.message,
        },
        "WYI3ob++++++++"
      )
      .then(
        () => {
          alert("Thank you for your message!");

          setForm({
            name: "",
            email: "",
            message: "",
          });
        },
        (error: Error) => {
          console.log(error);
          alert("Something went wrong");
        }
      );
  };

  return (
    <form
      ref={formRef}
      onSubmit={handleSubmit}
      className="flex flex-col gap-y-4"
    >
      <div className="relative flex items-center">
        <Input
          onChange={handleChange}
          type="text"
          id="name"
          placeholder="Name"
          required
          value={form.name}
        />
        <User className="absolute right-6" size={20} />
      </div>
      <div className="relative flex items-center">
        <Input
          onChange={handleChange}
          type="email"
          id="email"
          placeholder="Email"
          required
          value={form.email}
        />
        <MailIcon className="absolute right-6" size={20} />
      </div>
      <div className="relative flex items-center">
        <Textarea
          onChange={handleChange}
          required
          placeholder="Type your message"
          value={form.message}
        />
        <MessageSquare className="absolute top-4 right-6" size={20} />
      </div>

      <Button className="flex items-center gap-x-1 max-w-[166px] rounded-[80px]">
        Let&apos; s Talk
        <ArrowRightIcon size={20} />
      </Button>
    </form>
  );
};

export default Form;

Right now I am not able to type anything in the input or even copy, it is like they are stuck to the initial state of empty strings.

I am also using shadcn, in fact, the Input and TextArea components come from there. Anyone knows why I am facing this problem?

I also tried to use normal input and text area but I still can't type into any of the inputs.

I also tried to use defaultValues and in that case I can type into the inputs but the object with name, email, and message remain an empty string.


Solution

  • The issue you're experiencing is likely due to the way you're handling the id attribute in your <Input /> and <Textarea /> components and not correctly associating the name attribute with your form's state.

    For the useState hook to correctly update the state based on input changes, you need to ensure that the name attribute of each input matches the keys in your state object.

    In your code, you're setting the id attribute for <Input /> and <Textarea />, but you're not setting their name attribute, which is essential for the handleChange function to update the state correctly based on which input is changed.

    The handleChange function uses the name attribute to determine which part of the state to update.

    Below is the updated return () function based off of your shared code:

      return (
        <form
          ref={formRef}
          onSubmit={handleSubmit}
          className="flex flex-col gap-y-4"
        >
          <div className="relative flex items-center">
            <Input
              name="name" // Add the name attribute
              onChange={handleChange}
              type="text"
              id="name"
              placeholder="Name"
              required
              value={form.name}
            />
            <User className="absolute right-6" size={20} />
          </div>
          <div className="relative flex items-center">
            <Input
              name="email" // Add the name attribute
              onChange={handleChange}
              type="email"
              id="email"
              placeholder="Email"
              required
              value={form.email}
            />
            <MailIcon className="absolute right-6" size={20} />
          </div>
          <div className="relative flex items-center">
            <Textarea
              name="message" // Add the name attribute
              onChange={handleChange}
              required
              placeholder="Type your message"
              value={form.message}
            />
            <MessageSquare className="absolute top-4 right-6" size={20} />
          </div>
    
          <Button className="flex items-center gap-x-1 max-w-[166px] rounded-[80px]">
            Let&apos; s Talk
            <ArrowRightIcon size={20} />
          </Button>
        </form>
      );