react-hook-form / devtools

📋 DevTools to help debug forms.
https://react-hook-form.com/dev-tools
MIT License
638 stars 48 forks source link

Next.js Text content does not match server-rendered HTML. #178

Open parkgang opened 1 year ago

parkgang commented 1 year ago

Overview

The problem occurs in the versions below.

"next": "^12.3.1"
"react": "18.2.0"
"react-dom": "18.2.0"

An easy setup for that test is to run the command below.

npx create-next-app@latest --ts

error symptom

image

Resolution

I downgraded the react version to 17 and the problem did not occur. Something seems to be a problem between react@18 and next.js.

"react": "^17.0.2",
"react-dom": "^17.0.2",
bluebill1049 commented 1 year ago

you could use next/dynamic ssr:false with nextjs

parkgang commented 1 year ago

you could use next/dynamic ssr:false with nextjs

I want to do something, but I get a type error. Do you know the expected reason?

const DevTool = dynamic(
  () => import("@hookform/devtools").then((mod) => mod.DevTool),
  {
    ssr: false,
  }
);

image

I followed the official document of Next.js, but I have a question because I couldn't infer it as a component.

parkgang commented 1 year ago

To check if the grammar was wrong, I created a Test Component component and proceeded cleanly as follows, but no problem occurred.

import { useForm, SubmitHandler } from "react-hook-form";
import dynamic from "next/dynamic";

const Test = dynamic(() => import("./Test").then((mod) => mod.Test), {
  ssr: false,
});
const DevTool = dynamic(
  () => import("@hookform/devtools").then((mod) => mod.DevTool),
  {
    ssr: false,
  }
);

type Inputs = {
  example: string;
  exampleRequired: string;
};

export default function Home() {
  const {
    register,
    control,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<Inputs>();
  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);

  console.log(watch("example"));

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input defaultValue="test" {...register("example")} />
        <input {...register("exampleRequired", { required: true })} />
        {errors.exampleRequired && <span>This field is required</span>}
        <input type="submit" />
      </form>
      {/* OK */}
      <Test />
      {/* Type Error */}
      <DevTool control={control} />
    </>
  );
}

I suspect something is wrong with the types below.

image

parkgang commented 1 year ago

I haven't been able to find a solution other than changing the state so that it can only be displayed on the Client Side .

This is a cumbersome code base that you have to go through every time you use DevTool .

I don't think this is the best way.

import { useForm, SubmitHandler } from "react-hook-form";
import { DevTool } from "@hookform/devtools";
import { useEffect, useState } from "react";

type Inputs = {
  example: string;
  exampleRequired: string;
};

export default function Home() {
  const {
    register,
    control,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<Inputs>();

  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data);

  console.log(watch("example"));

  // Control with state to render only on the Client Side
  const [isDevToolEnabled, setIsDevToolEnabled] = useState<boolean>(false);
  useEffect(() => {
    setIsDevToolEnabled(true);
  }, []);

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <input defaultValue="test" {...register("example")} />
        <input {...register("exampleRequired", { required: true })} />
        {errors.exampleRequired && <span>This field is required</span>}
        <input type="submit" />
      </form>

      {/* I didn't want to create a state, so I tried the code below, but it caused a problem */}
      {/* {typeof window !== "undefined" && <DevTool control={control} />} */}

      {/* The solution is to display it on the screen by changing the state in the case of the client side as follows */}
      {isDevToolEnabled && <DevTool control={control} />}
    </>
  );
}
manudeli commented 1 year ago

you could use next/dynamic ssr:false with nextjs

I want to do something, but I get a type error. Do you know the expected reason?

const DevTool = dynamic(
  () => import("@hookform/devtools").then((mod) => mod.DevTool),
  {
    ssr: false,
  }
);

image

I followed the official document of Next.js, but I have a question because I couldn't infer it as a component.

I met Same problem. even if I use dynamic as @bluebill1049's suggestion.