Next js 错误“警告:预期服务器 HTML 包含匹配的 <button>在<div> [英] Next js Error "Warning: Expected server HTML to contain a matching <button> in <div>"

查看:40
本文介绍了Next js 错误“警告:预期服务器 HTML 包含匹配的 <button>在<div>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个暗模式组件,它是在 Sun 和月亮图标.

I have a Dark Mode component which is a simple toggle between Sun & Moon icons.

import { observer } from 'mobx-react'
import { MoonIcon, SunIcon } from '@heroicons/react/solid'

import { useStore } from '@/store/index'

export const DarkMode = observer(() => {
    const { theme, setTheme, isPersisting } = useStore()

    if (!isPersisting) return null

    return (
        <>
            {theme === 'dark' && (
                <button
                    className="fixed bottom-12 right-12 focus:outline-none"
                    title="Activate light mode"
                    onClick={() => {
                        setTheme('light')
                    }}
                >
                    <MoonIcon className="w-8 h-8" />
                </button>
            )}
            {theme === 'light' && (
                <button
                    className="fixed bottom-12 right-12 focus:outline-none"
                    title="Activate dark mode"
                    onClick={() => {
                        setTheme('dark')
                    }}
                >
                    <SunIcon className="w-8 h-8" />
                </button>
            )}
        </>
    )
})

我正在使用 MobX 来跟踪我的 主题 &mobx-persist-store 将数据保存在 localStorage 中.

I am using MobX to track my theme & mobx-persist-store to persist the data in localStorage.

import { makeObservable, observable, action } from 'mobx'
import { makePersistable, isPersisting, clearPersistedStore } from 'mobx-persist-store'

import type { Theme, IStore } from '@/types/index'

const name = 'Store'
const IS_SERVER = typeof window === 'undefined'

export class Store implements IStore {
    theme: Theme = 'light'

    constructor() {
        makeObservable(this, {
            theme: observable,
            setTheme: action.bound,
            reset: action.bound,
        })

        if (!IS_SERVER) {
            makePersistable(this, { name, properties: ['theme'], storage: window.localStorage })
        }
    }

    setTheme(theme: Theme) {
        this.theme = theme
    }

    get isPersisting() {
        return isPersisting(this)
    }

    async reset() {
        if (!IS_SERVER) await clearPersistedStore(this)
    }
}

当用户在暗模式组件中选择 dark 主题时,我将 dark 类添加到 html.

And I am adding dark class to html when the user selectes dark theme in Dark Mode component.

import React from 'react'
import { AppProps } from 'next/app'
import Head from 'next/head'
import { observer } from 'mobx-react'
import useSystemTheme from 'use-system-theme'

import { useStore } from '@/store/index'

import '@/components/NProgress'

import 'nprogress/nprogress.css'
import '@/styles/index.css'

const MyApp = ({ Component, pageProps }: AppProps) => {
    const systemTheme = useSystemTheme()
    const { theme, setTheme } = useStore()

    React.useEffect(() => {
        const isDarkTheme = theme === 'dark' || (systemTheme === 'dark' && theme !== 'light')
        if (isDarkTheme) {
            document.documentElement.classList.add('dark')
            setTheme('dark')
        } else {
            document.documentElement.classList.remove('dark')
            setTheme('light')
        }
    }, [theme, systemTheme])

    return (
        <>
            <Component {...pageProps} />
        </>
    )
}

export default observer(MyApp)

我仍然收到一条错误消息:

I am still getting an error that says:

VM356 main.js:16820 Warning: Expected server HTML to contain a matching <button> in <div>.
    at button
    at wrappedComponent (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624277701361:2690:73)
    at Nav (http://localhost:3000/_next/static/chunks/pages/tutorial/the-complete-guide-to-starting-a-blog-in-nextjs-and-mdx.js?ts=1624277701361:12454:23)
    at Tutorial (http://localhost:3000/_next/static/chunks/pages/tutorial/the-complete-guide-to-starting-a-blog-in-nextjs-and-mdx.js?ts=1624277701361:12973:24)
    at MDXLayout
    at http://localhost:3000/_next/static/chunks/pages/tutorial/the-complete-guide-to-starting-a-blog-in-nextjs-and-mdx.js?ts=1624277701361:7880:30
    at MDXContent (http://localhost:3000/_next/static/chunks/pages/tutorial/the-complete-guide-to-starting-a-blog-in-nextjs-and-mdx.js?ts=1624277701361:22563:25)
    at wrappedComponent (http://localhost:3000/_next/static/chunks/pages/_app.js?ts=1624277701361:2690:73)
    at ErrorBoundary (http://localhost:3000/_next/static/chunks/main.js?ts=1624277701361:767:47)
    at ReactDevOverlay (http://localhost:3000/_next/static/chunks/main.js?ts=1624277701361:883:23)
    at Container (http://localhost:3000/_next/static/chunks/main.js?ts=1624277701361:8756:5)
    at AppContainer (http://localhost:3000/_next/static/chunks/main.js?ts=1624277701361:9244:24)
    at Root (http://localhost:3000/_next/static/chunks/main.js?ts=1624277701361:9380:25)

buttononClick 事件处理程序从 DOM 本身消失.

The button's onClick event handler disappears from the DOM itself.

有趣的是它过去可以在 MacOS 上运行,但不能在 Windows 上运行.我克隆了同一个项目.有什么问题?

Funny thing is it used to work on MacOS but not on Windows. I cloned the same project. What's the issue?

推荐答案

我已经把我的 Nav 包裹在 ThemeProvider 之外.

The missing piece of the puzzle was I had wrapped my Nav outside of ThemeProvider.

Nav 包含 DarkMode,因此无法访问 ThemeProvider.我的 _document.tsx 看起来像:

Nav contained DarkMode so it couldn't access ThemeProvider. My _document.tsx looked like:

<Nav />
<ThemeProvider attribute="class" themes={['light', 'dark']}>
    <Component {...pageProps} />
</ThemeProvider>

所以我必须将 Nav 带入 ThemeProvider 以使其正常工作.

So I had to bring that Nav inside ThemeProvider to get it working.

<ThemeProvider attribute="class" themes={['light', 'dark']}>
    <Nav />
    <Component {...pageProps} />
</ThemeProvider>

这篇关于Next js 错误“警告:预期服务器 HTML 包含匹配的 &lt;button&gt;在&lt;div&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆