Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DevTools causes hydration errrors on page refresh in Next.js #187

Open
raleigh9123 opened this issue Dec 30, 2022 · 3 comments
Open

DevTools causes hydration errrors on page refresh in Next.js #187

raleigh9123 opened this issue Dec 30, 2022 · 3 comments

Comments

@raleigh9123
Copy link

I thought I had done something wonky in my app when these errors started appearing. I rolled back on some changes and learned that they appeared when I refresh the page that has the component imported.

I am working within a Blitz.js app which is built on Next.js (I am unsure, but am lead to believe that this is a problem within Next.js?)

The

component used by default in the Blitz.js installation is a little bit of a beast, in my opinion, and I added a couple more details to allow me to pass a custom prop to the child inputs.

My Form Component

// src / core / components / Form.tsx
// --> COMPONENT <-

// Node Modules Imports
import { useState, ReactNode, PropsWithoutRef, Children, cloneElement } from "react"
import { FormProvider, useForm, UseFormProps } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { DevTool } from "@hookform/devtools"

// TS Declarations
export interface FormProps<S extends z.ZodType<any, any>>
  extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
  /** All your form fields */
  children?: ReactNode
  /** Text to display in the submit button */
  schema?: S
  onSubmit: (values: z.infer<S>) => Promise<void | OnSubmitResult>
  initialValues?: UseFormProps<z.infer<S>>["defaultValues"]
  formtype?: string
}

interface OnSubmitResult {
  FORM_ERROR?: string
  [prop: string]: any
}

export const FORM_ERROR = "FORM_ERROR"

export function Form<S extends z.ZodType<any, any>>({
  children,
  schema,
  initialValues,
  onSubmit,
  formtype = "submit",
  ...props
}: FormProps<S>) {
  const ctx = useForm<z.infer<S>>({
    mode: "onChange",
    resolver: schema ? zodResolver(schema) : undefined,
    defaultValues: initialValues,
  })
  const [formError, setFormError] = useState<string | null>(null)

  let isProd = process.env.NODE_ENV === "production"

  return (
    <FormProvider {...ctx}>
      <form
        onSubmit={ctx.handleSubmit(async (values) => {
          const result = (await onSubmit(values)) || {}
          for (const [key, value] of Object.entries(result)) {
            if (key === FORM_ERROR) {
              setFormError(value)
            } else {
              ctx.setError(key as any, {
                type: "submit",
                message: value,
              })
            }
          }
        })}
        className="space-y-4"
        {...props}
      >
        {/* Form fields supplied as children are rendered here */}
        {Children.map(children, (child) =>
          cloneElement(child as React.ReactElement, { formtype })
        )}

        {formError && (
          <div role="alert" className="text-salmon-500 text-center">
            {formError}
          </div>
        )}


      </form>
      {!isProd && <DevTool control={ctx.control} /> }

    </FormProvider>
  )
}

export default Form

Again, the hydration errors ONLY occur when I refresh the page. They are listed in the following screenshot. I have not tried anything as a solution, but they do not appear when I remove the component.

Screenshot 2022-12-29 at 10 51 22 PM

The following is my package.json dependencies:

"dependencies": {
    "@blitzjs/auth": "2.0.0-beta.19",
    "@blitzjs/next": "2.0.0-beta.19",
    "@blitzjs/rpc": "2.0.0-beta.19",
    "@headlessui/react": "1.7.7",
    "@heroicons/react": "2.0.13",
    "@hookform/error-message": "2.0.1",
    "@hookform/resolvers": "2.9.10",
    "@prisma/client": "4.8.0",
    "blitz": "2.0.0-beta.19",
    "framer-motion": "7.10.2",
    "next": "12.2.5",
    "node-device-detector": "2.0.9",
    "postmark": "3.0.14",
    "prisma": "4.8.0",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-hook-form": "7.40.0",
    "react-icons": "4.7.1",
    "zod": "3.20.2"
  },
  "devDependencies": {
    "@hookform/devtools": "4.3.0",
    "@next/bundle-analyzer": "12.0.8",
    "@tailwindcss/forms": "0.5.3",
    "@testing-library/jest-dom": "5.16.3",
    "@testing-library/react": "13.4.0",
    "@testing-library/react-hooks": "8.0.1",
    "@types/jest": "29.2.2",
    "@types/node": "18.11.9",
    "@types/preview-email": "2.0.1",
    "@types/react": "18.0.25",
    "@typescript-eslint/eslint-plugin": "5.30.5",
    "autoprefixer": "10.4.13",
    "eslint": "8.27.0",
    "eslint-config-next": "12.3.1",
    "eslint-config-prettier": "8.5.0",
    "husky": "8.0.2",
    "jest": "29.3.0",
    "jest-environment-jsdom": "29.3.0",
    "lint-staged": "13.0.3",
    "postcss": "8.4.19",
    "prettier": "^2.7.1",
    "prettier-plugin-prisma": "4.4.0",
    "pretty-quick": "3.1.3",
    "preview-email": "3.0.7",
    "tailwindcss": "3.2.4",
    "ts-jest": "28.0.7",
    "typescript": "^4.8.4"
  },
@Nurou
Copy link

Nurou commented Dec 31, 2022

@raleigh9123 I've the same issue in a next.js app caused by DevTools. I use the following dynamic import workaround for now:

const DevT = dynamic(
  () =>
    import('@hookform/devtools').then((module) => {
      return module.DevTool
    }),
  { ssr: false },
)

@adamwdennis
Copy link

@Nurou 's answer worked for me! Thank you!!

Here's a slightly updated, typescript-compatible version of it that worked for me (hope it can save a few minutes for others like me who enjoy having a painful eslint config 😄 ):

import dynamic from 'next/dynamic';
const DevT: React.ElementType = dynamic(
  () => import('@hookform/devtools').then((module) => module.DevTool),
  { ssr: false }
);

Then, (like @Nurou insinuates), I can use it like so:

...
return (
  <FormProvider {...methods}>
    <DevT control={methods.control} placement="top-left" />
    ...
  </FormProvider>
)

@mohaimenkhalid
Copy link

@adamwdennis cool.. working..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants