Home > Software design >  React hook form show errrors block when state is passed
React hook form show errrors block when state is passed

Time:12-16

following the replies below I now have the following

import { useState } from "react";
import Head from "next/head";
import Link from "next/link";
import Image from "next/image";
import Background from "../../../../public/images/option1.png";
import Router from "next/router";
import { signIn } from "next-auth/client";
import { useForm } from "react-hook-form";
import { ErrorMessage } from "@hookform/error-message";
import { SaveIcon } from "@heroicons/react/outline";

export default function Confirm() {
  const {
    register,
    formState: { errors },
    handleSubmit,
  } = useForm({
    criteriaMode: "all",
  });

  const [old_password, setOldPassword] = useState("");
  const [password, setPassword] = useState("");
  const [confirm_password, setConfirmPassword] = useState("");

  const onSubmit = async () => {
    const status = await signIn("credentials", {
      redirect: false,
      email: email,
    });

    Router.push("/dashboard");
  };

  return (
    <>
      <Head>
        <title>Ellis Development - Confirm Password</title>
      </Head>

      <div className="relative">
        <div className="md:flex">
          {/* Image */}
          <div className="flex items-center justify-center bg-blue-700 h-screen lg:w-96">
            <Image src={Background} width={350} height={350} layout="fixed" />
          </div>

          {/* Contact form */}
          <div className="flex flex-col justify-center py-10 px-6 sm:px-10 w-full">
            <h1 className="text-4xl font-extrabold text-grey-800">
              Reset your password
            </h1>

            {/* errors */}
            <ErrorMessage
              errors={errors}
              name="formErrors"
              render={({ messages }) =>
                messages && (
                  <div className="mt-6 border-2 border-red-600">
                    <div className="bg-red-600 text-white py-2 px-4">
                      <h6>Following errors have occurred</h6>
                    </div>

                    <div className="text-grey-800 py-2 px-4">
                      <div className="flex flex-col gap-2">
                        {Object.entries(messages).map(([type, message]) => (
                          <div
                            className="flex flex-col gap-y-6 sm:gap-x-8"
                            key={type}
                          >
                            <small className="text-red-500">{message}</small>
                          </div>
                        ))}
                      </div>
                    </div>
                  </div>
                )
              }
            />

            <form
              onSubmit={handleSubmit(onSubmit)}
              className="mt-6 flex flex-col gap-y-6 sm:gap-x-8"
            >
              {/* old_password field */}
              <div>
                <label
                  htmlFor="old_password"
                  className="block text-sm font-medium text-gray-900"
                >
                  Old Password
                </label>

                <div className="mt-1">
                  <input
                    {...register("formErrors", {
                      required: "Old password is required",
                    })}
                    type="password"
                    name="old_password"
                    id="old_password"
                    className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
                    onChange={(event) => setOldPassword(event.target.value)}
                  />
                </div>
              </div>

              {/* password field */}
              <div>
                <label
                  htmlFor="password"
                  className="block text-sm font-medium text-gray-900"
                >
                  Password
                </label>

                <div className="mt-1">
                  <input
                    {...register("formErrors", {
                      required: "Password is required",
                    })}
                    type="password"
                    name="password"
                    id="password"
                    className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
                    onChange={(event) => setPassword(event.target.value)}
                  />
                </div>
              </div>

              {/* confirm_password field */}
              <div>
                <label
                  htmlFor="confirm_password"
                  className="block text-sm font-medium text-gray-900"
                >
                  Confirm Password
                </label>

                <div className="mt-1">
                  <input
                    {...register("formErrors", {
                      required: "Confirm password is required",
                    })}
                    type="password"
                    name="confirm_password"
                    id="confirm_password"
                    className="py-3 px-4 block w-full shadow-sm text-gray-900 focus:ring-blue-700 focus:border-blue-900 border-gray-300 rounded-md"
                    onChange={(event) => setConfirmPassword(event.target.value)}
                  />
                </div>
              </div>

              <div className="flex items-center justify-between sm:col-span-2">
                <div>
                  <button
                    type="submit"
                    className="mt-2 mr-2 w-full inline-flex items-center justify-center px-6 py-3 border border-transparent rounded-md shadow-sm text-base font-medium text-white bg-blue-700 hover:bg-blue-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 sm:w-auto"
                  >
                    <SaveIcon className="w-4 h-4 mr-4" />
                    Submit
                  </button>
                </div>

                <div>
                  <Link href="/dashboard/auth/login">
                    <a className="underline decoration-blue-500 decoration-4 hover:decoration-2 mr-4">
                      Login
                    </a>
                  </Link>
                </div>
              </div>
            </form>
          </div>
        </div>
      </div>
    </>
  );
}

However, only one of the errors is showing, enter image description here

There are multiple input fields and I have took a look at the docs, not sure what I'm doing wrong though.

original question I'm currently using the react-hook-form library, I have all of the errors above the form like so

{/* errors */}
{errors.length > 0 && (
  <div className="mt-6 border-2 border-red-600">
    <div className="bg-red-600 text-white py-2 px-4">
      <h4>{errors.length} errors occurred:</h4>
    </div>

    <div className="text-grey-800 py-2 px-4">
      <div className="flex flex-col gap-2">
        {/* old_password errror */}
        <div className="flex flex-col gap-y-6 sm:gap-x-8">
          {errors.old_password && (
            <small className="text-red-500">
              &bull; Old password is required
            </small>
          )}
        </div>

        {/* password error */}
        <div className="flex flex-col gap-y-6 sm:gap-x-8">
          {errors.password && (
            <small className="text-red-500">
              &bull; Password is required
            </small>
          )}
        </div>

        {/* confirm_password errror */}
        <div className="flex flex-col gap-y-6 sm:gap-x-8">
          {errors.confirm_password && (
            <small className="text-red-500">
              &bull; Confirm password is required
            </small>
          )}
        </div>
      </div>
    </div>
  </div>
)}

This works and the errors show, not sure if there's a way to map the errors to make the code more clear so any ideas there would be great.

However, how to I go about hiding the errors block, I have {errors.length > 0 && (, however this doesn't seem to work.

Here is a visual look enter image description here

Any help would be great.

CodePudding user response:

Since errors is a object .length won't work for it. But you can use Object.keys(errors).length > 0 to dynamic display the error block. Something like that:

{Object.keys(errors).length > 0 && (
  <div className="mt-6 border-2 border-red-600">
    <div className="bg-red-600 text-white py-2 px-4">
      <h6>Following errors have occurred</h6>
    </div>
    <div className="text-grey-800 py-2 px-4">
      <div className="flex flex-col gap-2">
        {/* Here you put one ErrorMessage for each input*/}
        <ErrorMessage
          errors={errors}
          name="old_password"
          render={({ message }) => (
            <div className="flex flex-col gap-y-6 sm:gap-x-8" key={type}>
              <small className="text-red-500">{message}</small>
            </div>
          )}
        />
      </div>
    </div>
  </div>

You input must be like this:

<input
  {...register("old_password", { required: "Old password is required" })}
  id="old_password"
  type="password"
  className="your classes"
  onChange={(event) => setOldPassword(event.target.value)}
/>
  • Related