Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useColorMode function that waits for mount before returning resolved theme #65

Closed
remorses opened this issue Nov 10, 2021 · 4 comments

Comments

@remorses
Copy link

Currently useTheme does not wait for react mount before returning the resolved theme

This means that in the following example resolvedTheme will be different between server and client, which will cause the react rehydration mismatch error

const theme = useTheme()
return theme === 'dark' ? <DarkIcon/> : <LightIcon/>

There could be another function that waits for react mount before changing the theme on client, to prevent these react errors, something like this

export function useColorMode({ defaultTheme = 'light' } = {}) {
    const { resolvedTheme: _resolvedTheme, setTheme } = useNextTheme()

    const [resolvedTheme, setResolvedTheme] = useState(defaultTheme)

    // wait for mount before changing theme
    useEffect(() => {
        setResolvedTheme(_resolvedTheme)
    }, [_resolvedTheme])

    return {
        resolvedTheme,
        setTheme,
  
    }
}

I can make a PR if you agree

@pacocoursey
Copy link
Owner

How is this better than returning undefined, as the hook currently does? It's documented in the README that you need to be careful about hydration mismatch: https://github.com/pacocoursey/next-themes#avoid-hydration-mismatch

@remorses
Copy link
Author

I think returning undefined in useTheme is not really helpful, i cannot use useTheme directly without using first useMount

What about adding an argument defaultTheme to useTheme?

import { useTheme } from 'next-themes'

const ThemeChanger = () => {

  const { theme, setTheme } = useTheme({ defaultTheme: 'light' })

  return (
    <div>
      The current theme is: {theme}
      <button onClick={() => setTheme('light')}>Light Mode</button>
      <button onClick={() => setTheme('dark')}>Dark Mode</button>
    </div>
  )
}

This would make things a lot easier

@pacocoursey
Copy link
Owner

If you already know the default theme... why not just use it directly?

const { theme = 'light', setTheme } = useTheme()

This way if theme is undefined, it will become 'light' instead :)

@pacocoursey
Copy link
Owner

Closing because I think your use-case should be solved with the above, and I don't think another hook will help here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants