reactjstypescriptnext.jsreact-hook-formreact-quill

react quill with react hook form & nextjs


I'm implementing editor using react-quill, react-hook-form in nextjs.

const QuillNoSSRWrapper = dynamic(import('react-quill'), {
  ssr: false,
  loading: () => <p>Loading ...</p>,
});

const Editor = () => {
  const { register, handleSubmit, watch, setValue } = useForm<Content>();

  useEffect(() => {
    if (document) {
      register('content', { required: true });
    }
  }, [register]);

  const onValid = (data: Content) => {
    console.log(data);
  };
  const editorChange = (editorState: string) => {
    setValue('content', editorState);
  };

  const editorContent = watch('content');
  return (
    <div onSubmit={handleSubmit(onValid)}>
      <QuillNoSSRWrapper
        value={editorContent}
        modules={modules}
        formats={formats}
        onChange={editorChange}
      />
      <input type="submit" />
    </div>
  );
};


enter image description here

I tried to add if(document)... but same error.

So, I changed form to div

like this

    <form>
      <QuillNoSSRWrapper
        value={editorContent}
        modules={modules}
        formats={formats}
        onChange={editorChange}
      />
      <input type="submit" onClick={handleSubmit(onValid)} />
    </form>

The data ​​I entered are shown in the console, but when I refresh I get the same error again.

Is there no way to use the form tag without using a div? I am trying to implement with react hook form.


Solution

  • I solved the Hydration error that I had in NextJS v13 using the following trick to only render the form during the client rendering and not during the SSR:

    export function LoginForm() {
      const [initialRenderComplete, setInitialRenderComplete] = useState(false)
    
      // This useEffect will only run once, during the first client render
      useEffect(() => {
        // Updating a state causes a re-render
        setInitialRenderComplete(true)
      }, [])
    
      return (
        <div>
          /* more html here if necessary ... */
    
          {initialRenderComplete && (
            <form>
              <input .... />
              <submit .... />
            </form>
          )}
    
        </div>
      )
    }
    

    Take a look at this article that explains very well the issue: https://www.joshwcomeau.com/react/the-perils-of-rehydration/