Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My Next.js component is rendering cumulatively again and again after the form is submitted

I am building a memory game app with Next.js, Node.js, and Express.js. I have a problem with the login page.

There is no problem first submitting the form. But after first submitting the form Login component re-renders more than once.

As the number of form submissions increases, the number of re-render increases as cumulative. Why does this happen?

When I click the submit button component needs to be rendered once, but the component re-renders so many times.

Codes:

"use client";

import React from "react";
import { z } from "zod";

import styles from "./index.module.scss";
import "./index.module.scss";
import Link from "next/link";

import { useGetUserMutation } from "@/src/app/store/features/api/apiSlice";

function Login() {
  console.log("resfles");
  const [isErrExist, setIsErrExist] = React.useState({
    status: false,
    emailText: "",
    passwordText: "",
  });
  const [getUser, { isLoading, data }] = useGetUserMutation();

  const userSchema = z.object({
    email: z.string().email(),
    password: z
      .string()
      .min(6, { message: "Your Password must have to minumum 5 character" })
      .max(10, { message: "Your Password must maximum 10 characters" }),
  });

  if (typeof window !== "undefined") {
    document.getElementById("form_")?.addEventListener("submit", (e) => {
      e.preventDefault();

      const spanOne = document.getElementById("spnOne") as HTMLElement;
      const spanTwo = document.getElementById("spnTwo") as HTMLElement;

      spanOne.innerHTML = "";
      spanTwo.innerHTML = "";

      const _form = document.getElementById("form_") as HTMLFormElement;
      const formData = new FormData(_form);

      const email = formData.get("email")?.toString();
      const password = formData.get("password")?.toString();

      if (typeof email !== undefined && typeof password !== undefined) {
        const data_ = Object.create(null);
        Object.defineProperties(data_, {
          email: {
            value: email,
            writable: true,
          },
          password: {
            value: password,
            writable: true,
          },
        });

        const result = userSchema.safeParse(data_);

        if (result.success) {
          console.log(data_);
          getUser({
            email: data_.email,
            password: data_.password,
          })
            .unwrap()
            .then((res) => console.log(res))
            .catch((err) => console.log(err));

          spanOne.innerHTML = "";
          spanTwo.innerHTML = "";
        } else {
          setIsErrExist({ ...isErrExist, status: true });
          const errArr = result.error.issues;
          const errMail = errArr.find((item) => item.path[0] == "email");
          const errPas = errArr.find((item) => item.path[0] == "password");

          if (errMail !== undefined) {
            spanOne.innerHTML = errMail.message;
          }
          if (errPas !== undefined) {
            spanTwo.innerHTML = errPas.message;
          }
        }
      }
    });
  }
  return (
    <form id="form_" className={styles.form_}>
      <h2>Login</h2>
      <label htmlFor="email_">E-mail Adress:</label>
      <input type="text" name="email" id="email_" />
      <span
        id="spnOne"
        className={isErrExist.status ? styles.err : styles.errNone}
      >
        Deneme
      </span>
      <label htmlFor="password_">Password:</label>
      <input type="text" name="password" id="password_" />
      <span
        id="spnTwo"
        className={isErrExist.status ? styles.err : styles.errNone}
      >
        Deneme
      </span>
      <button type="submit"> {isLoading ? "Loading..." : "Send"} </button>
      <Link href="register">
        <h4>Go To Register Page</h4>
      </Link>
    </form>
  );
}

export default Login;
like image 382
Hakan Karayılmaz Avatar asked Dec 31 '25 19:12

Hakan Karayılmaz


1 Answers

Calling addEventListener and accessing DOM elements as in plain JavaScript is not what you should do in a React/Next.js code. Use the built-in JSX and hooks capabilities.

The behavior you are getting is due to the fact after each render, an additional event handler for submit is added, as you are not removing them.

You could create a handleSubmit function that you give to the form. And use useRef instead of calling getElementById, like so:

"use client";

// Previous imports ...

// New imports:
import { FormEvent, useRef } from "react";

function Login() {
  // Previous code ...

  // New code :
  const spanOneRef = useRef<HTMLSpanElement>(null);
  const spanTwoRef = useRef<HTMLSpanElement>(null);
  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    const spanOne = spanTwoRef.current!;
    const spanTwo = spanTwoRef.current!;

    spanOne.innerHTML = "";
    spanTwo.innerHTML = "";

    const _form = e.currentTarget;
    const formData = new FormData(_form);

    const email = formData.get("email")?.toString();
    const password = formData.get("password")?.toString();

    if (typeof email !== undefined && typeof password !== undefined) {
      const data_ = Object.create(null);
      Object.defineProperties(data_, {
        email: {
          value: email,
          writable: true,
        },
        password: {
          value: password,
          writable: true,
        },
      });

      const result = userSchema.safeParse(data_);

      if (result.success) {
        console.log(data_);
        getUser({
          email: data_.email,
          password: data_.password,
        })
          .unwrap()
          .then((res) => console.log(res))
          .catch((err) => console.log(err));

        spanOne.innerHTML = "";
        spanTwo.innerHTML = "";
      } else {
        setIsErrExist({ ...isErrExist, status: true });
        const errArr = result.error.issues;
        const errMail = errArr.find((item) => item.path[0] == "email");
        const errPas = errArr.find((item) => item.path[0] == "password");

        if (errMail !== undefined) {
          spanOne.innerHTML = errMail.message;
        }
        if (errPas !== undefined) {
          spanTwo.innerHTML = errPas.message;
        }
      }
    }
  };

  return (
    <form id="form_" className={styles.form_} onSubmit={handleSubmit}>
      <h2>Login</h2>
      <label htmlFor="email_">E-mail Adress:</label>
      <input type="text" name="email" id="email_" />
      <span
        id="spnOne"
        ref={spanOneRef}
        className={isErrExist.status ? styles.err : styles.errNone}
      >
        Deneme
      </span>
      <label htmlFor="password_">Password:</label>
      <input type="text" name="password" id="password_" />
      <span
        id="spnTwo"
        ref={spanTwoRef}
        className={isErrExist.status ? styles.err : styles.errNone}
      >
        Deneme
      </span>
      <button type="submit"> {isLoading ? "Loading..." : "Send"} </button>
      <Link href="register">
        <h4>Go To Register Page</h4>
      </Link>
    </form>
  );
}

export default Login;
like image 100
yousoumar Avatar answered Jan 03 '26 09:01

yousoumar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!