0

First I have tried looking on Google for an answer before asking this question. I am not sure why the linter is complaining about my code. I am getting the following warning:

./components/blocks/Contact.tsx
119:6  Warning: React Hook useEffect has missing dependencies: 'errors.email', 'errors.message', 'errors.name', and 'errors.phone'. Either include them or remove the dependency array.  react-hooks/exhaustive-deps

Tried wrapping my statements and code inside a function FormOnSubmit Still no luck.

Would highly appreciate if someone can share some advice on this on how to deal this.

My code:

"use client"

import { useCallback, useEffect, useState } from "react"
import { useForm, SubmitHandler } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z, ZodType } from "zod"
import validator from "validator"
import { FiUser, FiMail, FiPhone } from "react-icons/fi"

import { cn } from "@/lib/utils"

import { MaxWidthWrapper } from "@/components/ui"

import Button from "./Button"
import Alert from "./Alert"

const Contact = () => {
  const [characterLimit] = useState<number>(150)
  const [personName, setPersonName] = useState<string>()
  const [isSubmitted, setIsSubmitted] = useState<boolean>(false)
  const [showSuccess, setShowSuccess] = useState<boolean>(false)
  const [newMessage, setNewMessage] = useState<Contact>({
    name: "",
    email: "",
    phone: "",
    message: ""
  })

  const schema: ZodType<Contact> = z.object({
    name: z
      .string()
      .min(4, { message: "Naam moet minimaal 4 teken(s) bevatten" })
      .max(20, { message: "Naam mag maximaal 20 teken(s) bevatten" }),

    email: z.string().email({ message: "Ongeldig e-mailadres" }),

    phone: z
      .string()
      .min(10, { message: "Telefoonnummer moet minimaal 10 teken(s) bevatten" })
      .refine(validator.isMobilePhone, { message: "Ongeldige invoer" }),

    message: z
      .string()
      .min(20, { message: "Bericht moet minimaal 20 teken(s) bevatten" })
      .max(characterLimit, {
        message: `Bericht mag maximaal ${characterLimit} teken(s) bevatten`
      })
      .refine(validator.escape)
  })

  const {
    register,
    handleSubmit,
    reset,
    formState,
    clearErrors,
    formState: { errors, isSubmitSuccessful }
  } = useForm<Contact>({
    resolver: zodResolver(schema),
    defaultValues: {},
    reValidateMode: "onSubmit"
  })

  const handleInputChange = (
    e: React.FormEvent<HTMLInputElement> | React.FormEvent<HTMLTextAreaElement>
  ) => {
    setNewMessage({
      ...newMessage,
      [e.currentTarget.name]: e.currentTarget.value
    })

    e.currentTarget.name === "name" && clearErrors("name")
    e.currentTarget.name === "email" && clearErrors("email")
    e.currentTarget.name === "phone" && clearErrors("phone")
    e.currentTarget.name === "message" && clearErrors("message")
  }

  const onSubmit: SubmitHandler<Contact> = useCallback(
    (data) => {
      return new Promise<void>((resolve) => {
        resolve()

        setIsSubmitted(true)

        setPersonName(data.name)

        console.table(data)

        setNewMessage({
          ...newMessage,
          ...data
        })
      })
    },
    [newMessage]
  )

  useEffect(() => {
    const FormOnSubmit = () => {
      if (errors.email || errors.message || errors.name || errors.phone) {
        setShowSuccess(false)
      }

      if (isSubmitSuccessful) {
        setShowSuccess(true)

        reset({
          name: "",
          email: "",
          phone: "",
          message: ""
        })

        setNewMessage({ name: "", email: "", phone: "", message: "" })
      }
    }

    FormOnSubmit()
  }, [])

  const name = register("name")
  const email = register("email")
  const phone = register("phone")
  const message = register("message")

  return (
    <MaxWidthWrapper container>
      <div className="max-w-6xl pb-16 mx-auto text-midnight pt-7">
        <h2 className="text-3xl leading-none text-center sm:text-5xl lg:text-6xl font-playfair">
          Stel hier al je vragen!
        </h2>

        <p className="max-w-lg pt-4 pb-8 mx-auto text-center text-md">
          Lorem ipsum dolor sit amet consectetur adipisicing elit. In, odio
          illum reprehenderit necessitatibus esse ex eos dolor sapiente.
        </p>

        <form autoComplete="off" onSubmit={handleSubmit(onSubmit)}>
          <div className="gap-8 space-y-4 lg:gap-20 md:flex md:space-y-0">
            <div className="w-full space-y-4">
              <label className="block space-y-3">
                <span className="text-lg md:text-xl font-playfair">
                  Naam en achternaam*
                </span>
                <div className="relative flex items-center group">
                  <FiUser className="absolute w-6 h-6 pointer-events-none left-5 stroke-midnight" />
                  <input
                    {...name}
                    onChange={handleInputChange}
                    value={newMessage.name}
                    className={cn(
                      errors.name
                        ? "placeholder:text-red-800 border-red-800"
                        : "placeholder:text-midnight border-midnight",
                      "w-full py-3 text-sm md:text-base pr-5 bg-white border-1 text-midnight outline-none pl-14 rounded-xl disabled:bg-gray-100 disabled:placeholder:text-gray-400"
                    )}
                    placeholder="Naam en achternaam"
                  />
                </div>

                {errors.name && (
                  <p className="text-xs font-bold text-red-800">
                    {errors.name.message}
                  </p>
                )}
              </label>

              <label className="block space-y-3">
                <span className="text-lg md:text-xl font-playfair">
                  E-mailadres*
                </span>
                <div className="relative flex items-center group text-midnight">
                  <FiMail className="absolute w-6 h-6 pointer-events-none left-5" />
                  <input
                    {...email}
                    onChange={handleInputChange}
                    value={newMessage.email}
                    className={cn(
                      errors.email
                        ? "placeholder:text-red-800 border-red-800"
                        : "placeholder:text-midnight border-midnight",
                      "w-full py-3 text-sm md:text-base pr-5 bg-white border-1 text-midnight outline-none pl-14 rounded-xl disabled:bg-gray-100 disabled:placeholder:text-gray-400"
                    )}
                    placeholder="E-mailadres"
                  />
                </div>

                {errors.email && (
                  <p className="text-xs font-bold text-red-800">
                    {errors.email.message}
                  </p>
                )}
              </label>

              <label className="relative block space-y-3">
                <span className="text-lg md:text-xl font-playfair">
                  Telefoonnummer*
                </span>
                <div className="relative flex items-center group text-midnight">
                  <FiPhone className="absolute w-6 h-6 pointer-events-none left-5"></FiPhone>
                  <input
                    {...phone}
                    onChange={handleInputChange}
                    value={newMessage.phone}
                    maxLength={10}
                    className={cn(
                      errors.phone
                        ? "placeholder:text-red-800 border-red-800"
                        : "placeholder:text-midnight border-midnight",
                      "w-full py-3 text-sm md:text-base pr-5 bg-white border-1 text-midnight outline-none pl-14 rounded-xl disabled:bg-gray-100 disabled:placeholder:text-gray-400"
                    )}
                    placeholder="Telefoonnummer"
                  />
                </div>

                {errors.phone && (
                  <p className="text-xs font-bold text-red-800">
                    {errors.phone.message}
                  </p>
                )}
              </label>
            </div>

            <div className="w-full space-y-3">
              <label className="block space-y-3">
                <span className="text-lg md:text-xl font-playfair">
                  Je bericht*
                </span>
                <textarea
                  {...message}
                  onChange={handleInputChange}
                  value={newMessage.message}
                  rows={10}
                  className={cn(
                    errors.message
                      ? "placeholder:text-red-800 border-red-800"
                      : "placeholder:text-midnight border-midnight",
                    "w-full px-5 py-3 text-sm md:text-base bg-white text-midnight border-1 outline-none resize-none rounded-xl disabled:bg-gray-100 disabled:placeholder:text-gray-400"
                  )}
                  placeholder="Bericht..."
                />

                {errors.message && (
                  <p className="text-xs font-bold text-red-800">
                    {errors.message.message}
                  </p>
                )}
              </label>

              <div className="flex justify-between">
                <div
                  className={cn(
                    "badge font-semibold text-xs",
                    newMessage.message.length > characterLimit &&
                      "badge-error bg-red-800 text-white"
                  )}
                >
                  {newMessage.message.length}/{characterLimit}
                </div>

                <Button
                  buttonType="submit"
                  text="Versturen"
                  buttonClass="btn-secondary"
                />
              </div>
            </div>
          </div>

          {showSuccess && isSubmitted && (
            <Alert
              type="success"
              message={`Bedankt ${personName} voor het versturen van je bericht`}
            />
          )}
        </form>
      </div>
    </MaxWidthWrapper>
  )
}

export default Contact
Galanthus
  • 1,958
  • 3
  • 14
  • 35
  • have you checked this link ? https://stackoverflow.com/questions/55840294/how-to-fix-missing-dependency-warning-when-using-useeffect-react-hook – inkredusk Apr 18 '23 at 14:11
  • @inkredusk that's exactly the link I have checked and tried doing the same but no luck. – Galanthus Apr 18 '23 at 14:14

1 Answers1

1

UseEffect triggers (re-runs the logic) whenever any of the variables that are defined in the dependency array change. When none is defined, useEffect triggers only on(re)Mount of the component.

Sometimes you are leaving variables out of the dependency array on purpose, because you don't want to make a trigger dependent on them.

Missing dependencies is a linter warning (and not an error), because in some instances a developer is forgetting to add a variable that is used as part of the useEffect (which should cause a trigger). The linter calls it out for you, in case you are missing it. You can disable the warning with // eslint-disable-next-line react-hooks/exhaustive-deps, by placing it in the line above the dependency array.

Before you disable the warning, think about if you want the useEffect function to re-run or not, when the dependent variables change.

useEffect(() => {
    const FormOnSubmit = () => {
      if (errors.email || errors.message || errors.name || errors.phone) {
  ...

    FormOnSubmit()
  }, []) <---- dependency array
Michael Brenndoerfer
  • 3,483
  • 2
  • 39
  • 50
  • Thank you. What would be a better thing to do? Since I do need a on change event to check for errors and if fields are valid or empty etc. How can I fix this without disabling the warnings. – Galanthus Apr 18 '23 at 14:16
  • 1
    As mentioned, to disable the warning paste `// eslint-disable-next-line react-hooks/exhaustive-deps` above the dep array []. I believe you DO want the fields in the dep array. – Michael Brenndoerfer Apr 18 '23 at 14:49