Closed productdevbook closed 2 years ago
In SSR Mode. colorMode
is always light. It results in the SSR output using light theme variables & causes the style glitch.
If you want SSR page output correct result. You need to make theme a param of URL.
I don't really care if the SSR output respects the client's color scheme, but I'd at least like it to hydrate properly once rendered client side. This doesn't always seem to work as expected for some naive-ui components.
As you can see here, the SSR NButton
is rendered with the light theme, while the Client Only NButton
is rendered with dark (wrapped in ClientOnly
tag). In my experience, the only naive-ui
components that are hydrated correctly are those that are forced to load/reload client side (e.g. relying on async data or wrapped in ClientOnly
tag).
I'm sure there's a far better method for getting around this, but my simple hack was adding a plugin to hook into the page:finish
lifecycle hook
, and then simply toggle dark mode off and on (only if already enabled):
// plugins/setTheme.client.ts
export default defineNuxtPlugin((nuxtApp) => {
const isDark = useDark()
// SSR is causing dark mode hydration issues with naive-ui
// This fix quickly toggles dark mode on 'page:finish' hook
nuxtApp.hook('page:finish', () => {
setTimeout(() => {
const prefersDark = usePreferredDark()
isDark.value = false
setTimeout(() => {
isDark.value = prefersDark.value
}, 0)
}, 0)
})
return {
provide: {
isDark
}
}
})
<!-- app.vue -->
<template>
<div>
<nuxt-layout>
<n-config-provider :theme="$isDark ? darkTheme : lightTheme">
<n-message-provider>
<n-dialog-provider>
<nuxt-page />
</n-dialog-provider>
</n-message-provider>
</n-config-provider>
</nuxt-layout>
</div>
</template>
<script lang="ts" setup>
import { NMessageProvider, NConfigProvider, NDialogProvider } from 'naive-ui';
import { darkTheme, lightTheme } from 'naive-ui';
const { $isDark } = useNuxtApp()
</script>
I think this is still a bug. When the server renders, and then sends it to the client to render as well, the client actually gets the color pattern responsively and passes the prop to the NConfigProvider component accordingly, but the components don't respond to the change correctly.
Alternative workaround:
<NConfigProvider :theme>
<!-- your code here -->
</NConfigProvider>
import { darkTheme } from "naive-ui"
const theme = ref(null)
watchPostEffect(
() => theme.value = colorMode.value === "dark" ? darkTheme : null
)
The trick is the delayed theme change by watchPostEffect
.
TuSimple/naive-ui version (版本)
2.33.3
Vue version (Vue 版本)
3.2.39
Browser and its version (浏览器及其版本)
Version 105.0.5195.125 (Official Build) (64-bit)
System and its version (系统及其版本)
ubuntu 22
Node version (Node 版本)
16
Reappearance link (重现链接)
https://github.com/productdevbook/oku-nuxt3-template
Reappearance steps (重现步骤)
yarn install yarn dev
open -> http://localhost:3000/naive dark mode select refresh page
Expected results (期望的结果)
dark mode working
Actual results (实际的结果)
half dark half white mode
Remarks (补充说明)
and white this problem