最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Input Field in NextJS causing "Hydration Error and Did not expect server HTML to contain a <div&

programmeradmin2浏览0评论

as the title states I am creating a website using NextJS styled with TailwindCSS. However, there is a small and annoying issue with my code.

Here is my code below for the MainContent of the page:

"use client"
import React, {useState} from 'react';

export default function MainContent(){
    const [eventTerm, setSearchTerm] = useState('');
    const [zipCode, setZipCode] = useState('');

    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      setSearchTerm(event.currentTarget.value);
    }
    const handleZipChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setZipCode(event.currentTarget.value);
    }
    
    const handleSubmit = (event: React.ChangeEvent <HTMLButtonElement>) => {
      event.preventDefault();
      // Perform search functionality here
      console.log(eventTerm);
      console.log(zipCode);
    }
    return (
      <main>
        <div className = "max-w-7xl mx-5 px-5 sm:px-6 lg:px-8 my-auto py-9 mt-20 text-center">
          <h1 className = "font-rowdies md:text-7xl text-white sm:text-center md:text-left my-3">Test, <br/> Test </h1>
          <div className = "my-auto py-5">
          <small className = "font-rowdies md:text-3xl text-white md:block md:text-left my-1 flex-wrap sm:text-2xl break-words">Test</small>
          <div className="my-auto py-5 md:text-left">
          <form className = "relative rounded-lg bg-transparent"> 
            <input type="text" placeholder="Find a Service" defaultValue={eventTerm} onChange={handleChange} className="form-input mr-2 py-2 px-10 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-800 text-center font-rowdies"/>
            <input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/> 
            <button className = "bg-gray-900 text-white ml-2 px-3 py-2 rounded-md text-l font-rowdies hover:text-secondary hover:bg-white">Lets Go!</button>
          </form>
          </div>
          </div>
        </div>
      </main>
      )
}

The errors I am getting in chrome are: Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Did not expect server HTML to contain a in .

The issue seems to stem from this line only after refreshing the page not on the initial load

 <input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/> 

I say this because whenever I delete this line the 2 errors go away and my website works just fine.

In addition to this, I sent my friend the file and it ran fine on his computer. Stuff that I tried included checking that my dependencies were up-to-date and clearing my cache and cookies as well as other things with my code.

Any help would be greatly appreciated. I will also add a few more code snippets as well as a directory structure image.

Thanks!

HomePage.tsx

import React, { MouseEventHandler, useState } from 'react';
import { Disclosure, Menu, Transition } from '@headlessui/react'
import '../styles/globals.css'
import MainContent from './MainContent';
export default function (){
    const [isOpen, setIsOpen] = useState(false);
    return (
        <>
        <header>
        <div className = "items-center">
      <nav className = "justify-between bg-secondary">
        <div className = "mx-5 px-5 sm:px-6">
          <div className = "relative flex items-center justify-between h-16">
            <div className = "flex flex-grow-1 flex-shrink-1">
                <a href = "#" className="font-rowdies text-white text-3xl">Portfolio</a>
              </div>
              <div className = "hidden md:block items-end justify-end">
                <div className = "ml-10 flex items-end space-x-4">
                  <button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary hover:bg-secondary">Join as a Pro</button>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">Log In</a>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">Sign Up</a>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">About Us</a>
                </div>
              </div>
            <div className="-mr-2 flex md:hidden place-content-center">
              <button
                onClick={() => setIsOpen(!isOpen)}
                type="button"
                className="bg-gray-900 inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
                aria-controls="mobile-menu"
                aria-expanded="false"
              >
                <span className="sr-only">Open main menu</span>
                {!isOpen ? (
                  <svg
                    className="block h-6 w-6"
                    xmlns=";
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    aria-hidden="true"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M4 6h16M4 12h16M4 18h16"
                    />
                  </svg>
                ) : (
                  <svg
                    className="block h-6 w-6"
                    xmlns=";
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    aria-hidden="true"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M6 18L18 6M6 6l12 12"
                    />
                  </svg>
                )}
              </button>
            </div>
          </div>
        </div>

        <Transition
          show={isOpen}
          enter="transition ease-out duration-1000 transform"
          enterFrom="opacity-0 scale-95"
          enterTo="opacity-100 scale-100"
          leave="transition ease-in duration-75 transform"
          leaveFrom="opacity-100 scale-100"
          leaveTo="opacity-0 scale-95"
        >
          {(ref) => (
            <div className="md:hidden text-center bg-secondary" id="mobile-menu">
              <div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">Log In</a>
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">Sign Up</a>
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">About Us</a>
              <button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies block mx-auto hover:text-primary hover:bg-secondary">Join as a Pro</button>
              </div>
            </div>
          )}
        </Transition>
      </nav>
    </div>
    </header>
    <MainContent />
    </>
    )

}

Page.tsx

"use client";
import Image from 'next/image'
import { Inter } from '@next/font/google'
import styles from './page.module.css'
const inter = Inter({ subsets: ['latin'] })
import { useRouter } from "next/navigation";
import Homepage from '@/components/Homepage';
import MainContent from '@/components/MainContent';
import { Main } from 'next/document';
export default function Home() {
  return (
    <>
        <Homepage />
    </>
  )
}

Image of all my dependencies and their versions

as the title states I am creating a website using NextJS styled with TailwindCSS. However, there is a small and annoying issue with my code.

Here is my code below for the MainContent of the page:

"use client"
import React, {useState} from 'react';

export default function MainContent(){
    const [eventTerm, setSearchTerm] = useState('');
    const [zipCode, setZipCode] = useState('');

    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      setSearchTerm(event.currentTarget.value);
    }
    const handleZipChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setZipCode(event.currentTarget.value);
    }
    
    const handleSubmit = (event: React.ChangeEvent <HTMLButtonElement>) => {
      event.preventDefault();
      // Perform search functionality here
      console.log(eventTerm);
      console.log(zipCode);
    }
    return (
      <main>
        <div className = "max-w-7xl mx-5 px-5 sm:px-6 lg:px-8 my-auto py-9 mt-20 text-center">
          <h1 className = "font-rowdies md:text-7xl text-white sm:text-center md:text-left my-3">Test, <br/> Test </h1>
          <div className = "my-auto py-5">
          <small className = "font-rowdies md:text-3xl text-white md:block md:text-left my-1 flex-wrap sm:text-2xl break-words">Test</small>
          <div className="my-auto py-5 md:text-left">
          <form className = "relative rounded-lg bg-transparent"> 
            <input type="text" placeholder="Find a Service" defaultValue={eventTerm} onChange={handleChange} className="form-input mr-2 py-2 px-10 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-800 text-center font-rowdies"/>
            <input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/> 
            <button className = "bg-gray-900 text-white ml-2 px-3 py-2 rounded-md text-l font-rowdies hover:text-secondary hover:bg-white">Lets Go!</button>
          </form>
          </div>
          </div>
        </div>
      </main>
      )
}

The errors I am getting in chrome are: Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Did not expect server HTML to contain a in .

The issue seems to stem from this line only after refreshing the page not on the initial load

 <input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/> 

I say this because whenever I delete this line the 2 errors go away and my website works just fine.

In addition to this, I sent my friend the file and it ran fine on his computer. Stuff that I tried included checking that my dependencies were up-to-date and clearing my cache and cookies as well as other things with my code.

Any help would be greatly appreciated. I will also add a few more code snippets as well as a directory structure image.

Thanks!

HomePage.tsx

import React, { MouseEventHandler, useState } from 'react';
import { Disclosure, Menu, Transition } from '@headlessui/react'
import '../styles/globals.css'
import MainContent from './MainContent';
export default function (){
    const [isOpen, setIsOpen] = useState(false);
    return (
        <>
        <header>
        <div className = "items-center">
      <nav className = "justify-between bg-secondary">
        <div className = "mx-5 px-5 sm:px-6">
          <div className = "relative flex items-center justify-between h-16">
            <div className = "flex flex-grow-1 flex-shrink-1">
                <a href = "#" className="font-rowdies text-white text-3xl">Portfolio</a>
              </div>
              <div className = "hidden md:block items-end justify-end">
                <div className = "ml-10 flex items-end space-x-4">
                  <button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary hover:bg-secondary">Join as a Pro</button>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">Log In</a>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">Sign Up</a>
                  <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary">About Us</a>
                </div>
              </div>
            <div className="-mr-2 flex md:hidden place-content-center">
              <button
                onClick={() => setIsOpen(!isOpen)}
                type="button"
                className="bg-gray-900 inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
                aria-controls="mobile-menu"
                aria-expanded="false"
              >
                <span className="sr-only">Open main menu</span>
                {!isOpen ? (
                  <svg
                    className="block h-6 w-6"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    aria-hidden="true"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M4 6h16M4 12h16M4 18h16"
                    />
                  </svg>
                ) : (
                  <svg
                    className="block h-6 w-6"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor"
                    aria-hidden="true"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M6 18L18 6M6 6l12 12"
                    />
                  </svg>
                )}
              </button>
            </div>
          </div>
        </div>

        <Transition
          show={isOpen}
          enter="transition ease-out duration-1000 transform"
          enterFrom="opacity-0 scale-95"
          enterTo="opacity-100 scale-100"
          leave="transition ease-in duration-75 transform"
          leaveFrom="opacity-100 scale-100"
          leaveTo="opacity-0 scale-95"
        >
          {(ref) => (
            <div className="md:hidden text-center bg-secondary" id="mobile-menu">
              <div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">Log In</a>
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">Sign Up</a>
              <a href = "#" className = " text-white px-3 py-2 rounded-md text-l font-rowdies block hover:text-primary">About Us</a>
              <button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies block mx-auto hover:text-primary hover:bg-secondary">Join as a Pro</button>
              </div>
            </div>
          )}
        </Transition>
      </nav>
    </div>
    </header>
    <MainContent />
    </>
    )

}

Page.tsx

"use client";
import Image from 'next/image'
import { Inter } from '@next/font/google'
import styles from './page.module.css'
const inter = Inter({ subsets: ['latin'] })
import { useRouter } from "next/navigation";
import Homepage from '@/components/Homepage';
import MainContent from '@/components/MainContent';
import { Main } from 'next/document';
export default function Home() {
  return (
    <>
        <Homepage />
    </>
  )
}

Image of all my dependencies and their versions

Share Improve this question edited Dec 18, 2023 at 17:19 j08691 208k32 gold badges268 silver badges280 bronze badges asked Jan 26, 2023 at 0:32 apexapex 771 silver badge7 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 24

When I disabled the LastPass browser extension the problem went away. LastPass injects HTML post-load that throws off the comparison between SSR and client.

This same issue came up in Reddit.

A fairly elegant solution - if you don't mind forcing your component to be a Client Component - was landed:

'use client'

import {useState, useEffect} from 'react';
import Loading from './loading'; // assumes App Router in use with loading.jsx|tsx

export default function MyComponent() {
  ... // other hooks, like useFormState

  const [isClient, setIsClient] = useState(false);
  useEffect(() => {
    setIsClient(true);
  }, []);
  
  if (!isClient) return <Loading />;

  return ... // the real UI
}

Seems to work great:

  • solves the lastPass hydration errors - or any client-side element injection, presumably
  • having a loading.tsx file causes App Router to use a Suspense boundary, which avoids Client rendering the whole route in case of other hydration errors
  • mimics the UI behavior when dynamic rendering or streaming causes rendering delays

In Dashlane and Lastpass, you have an option to pause the autofill on certain website. While developing, turn off that autofill off on your localhost or your development host domain.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论