Search code examples
node.jsreactjsformsinputtextfield

Can't type in Reactjs input text field


I am starting my first bit of react.js, the code below creates two forms (login and register). Typing in the input text 'email' and 'password' goes smoothly while typing in the 'firstName' and 'lastName' fields does nothing.

I've created a component called 'FormField' which is a simple input text field.

Presumably, something is going missing passing the props and state up and down, and this seems like a common problem. But I'm stumped - I can't see what's missing.

app/routes/login.tsx

import { Layout } from "~/components/layout";
import { FormField } from "~/components/form-field";
import { useState } from "react";
import { ActionFunction, json } from "@remix-run/node";
import { login, register } from "~/utils/auth.server";

export default function Login() {
  const [action, setAction] = useState("login");
  const [formData, setFormData] = useState({
    email: "",
    password: "",
    firstname: "",
    lastname: "",
  });

  // Updates the form data when an input changes
  const handleInputChange = (
    event: React.ChangeEvent<HTMLInputElement>,
    field: string
  ) =>
    setFormData((form) => ({
      ...form,
      [field]: event.target.value,
    }));

  return (
    <Layout>
      <div className="h-full flex justify-center items-center flex-col gap-y-4">
        <button
          onClick={() => setAction(action == "login" ? "register" : "login")}
          className="absolute top-8 right-8 rounded-xl bg-yellow-300 font-semibold text-blue-600 px-3 py-2 translate duration-300 ease-in-out hover:bg-yellow-400 hover:-translate-y-1"
        >
          {action === "login" ? "Sign Up" : "Sign In"}
        </button>
        <h2 className="text-5xl font-extrabold text-yellow-400">
          Welcome to focus!
        </h2>
        <p className="font-semibold text-slate-300">
          {action === "login" ? "Log In" : "Sign Up"}
        </p>

        <form method="post" className="rounded-2xl bg-gray-200 p-6 w-96">
          <FormField
            htmlFor="email"
            label="Email"
            value={formData.email}
            onChange={(e) => handleInputChange(e, "email")}
          />
          <FormField
            htmlFor="password"
            label="Password"
            type="password"
            value={formData.password}
            onChange={(e) => handleInputChange(e, "password")}
          />

          {action !== "login" ? (
            <>
              <FormField
                htmlFor="firstName"
                label="First Name"
                value={formData.firstname}
                onChange={(e) => handleInputChange(e, "firstName")}
              />
              <FormField
                htmlFor="lastName"
                label="Last Name"
                value={formData.lastname}
                onChange={(e) => handleInputChange(e, "lastName")}
              />
            </>
          ) : null}

          <div className="m-full text-center">
            <button
              type="submit"
              name="_action"
              value={action}
              className="rounded-xl mt-2 bg-yellow-300 px-3 py-2 text-blue-600 font-semibold transition duration-300 ease-in-out hover:bg-yellow-400 hover:-translate-y-1"
            >
              {action === "login" ? "Sign In" : "Sign Up"}
            </button>
          </div>
        </form>
      </div>
    </Layout>
  );
}

Solution

  • In the initial state, you are using firstname and lastname, but in the handleInputChange function, you are updating the state using firstName and lastName.

      const [formData, setFormData] = useState({
        email: "",
        password: "",
        firstname: "",
        lastname: "",
      });
    
    

    JavaScript is case sensitive. Therefore, when you type in the firstName and lastName fields, the formData state is not getting updated.

    To fix this, you can update the initial state to use firstName and lastName instead of firstname and lastname:

    const [formData, setFormData] = useState({
      email: "",
      password: "",
      firstName: "",
      lastName: "",
    });
    
    

    or, you could make all the keys lowercase before comparing like so.

    const handleInputChange = (
      event: React.ChangeEvent<HTMLInputElement>,
      field: string
    ) =>
      setFormData((form) => ({
        ...form,
        [field.toLowerCase()]: event.target.value,
      }));