NextJS 中的输入字段导致“水合错误,并且没想到服务器 HTML 会在 <div> 中包含 <form>”,但仅在 Chrome 中且仅在我的计算机上

问题描述 投票:0回答:2

正如标题所述,我正在使用 NextJS 创建一个网站,并使用 TailwindCSS 进行样式设置。然而,我的代码有一个小而烦人的问题。

下面是我的页面主要内容的代码:

"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>
      )
}

我在 chrome 中遇到的错误是: 错误:水合失败,因为初始 UI 与服务器上呈现的内容不匹配。 警告:没想到服务器 HTML 中包含 .

问题似乎仅在刷新页面后才源于此行,而不是在初始加载时

 <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"/> 

我这么说是因为每当我删除这一行时,两个错误就会消失,并且我的网站工作得很好。

除此之外,我还向我的朋友发送了该文件,并且该文件在他的计算机上运行良好。我尝试的内容包括检查我的依赖项是否是最新的,并使用我的代码清除我的缓存和 cookie 以及其他内容。

任何帮助将不胜感激。我还将添加更多代码片段以及目录结构图像。

谢谢!

主页.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 />
    </>
    )

}

页面.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 />
    </>
  )
}

我所有依赖项及其版本的图像

javascript reactjs next.js web-deployment-project
2个回答
16
投票

当我禁用 LastPass 浏览器扩展后,问题就消失了。 LastPass 注入 HTML 后加载,从而消除了 SSR 和客户端之间的比较。


0
投票

同样的问题也出现在 Reddit 中。

一个相当优雅的解决方案 - 如果你不介意强制你的组件成为客户端组件 - 已经落地:

'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
}
© www.soinside.com 2019 - 2024. All rights reserved.