Next js 错误“警告:预期服务器 HTML 包含匹配的 <button>在<div> [英] Next js Error "Warning: Expected server HTML to contain a matching <button> in <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)
button
的 onClick
事件处理程序从 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 包含匹配的 <button>在<div>的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!