-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
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
useColorMode()
cannot safely be used with SSR
#9629
Comments
Oh I probably should have searched before I made this. Looks like #7986 is effectively the same thing. |
For this specific case of issue of code highlighting, I bet I could make a custom prism theme that uses variables set by style with html data theme selector like other responsive UI does. |
Yes this is a known issue. At build time we have to pick one color mode to render the static pages, and cannot read OS settings or localStorage there so we have to pick one or another. At hydration time we should hydrate with the exact same color that was used at build time (I don't think we do this correctly atm), and only then update the color in React state to match the actual rendered value. We inline critical JS in the page to render the correct color mode through CSS selectors, before the hydration, this is what prevents our theme to have a flash. Unfortunately, React has to see the real color mode a bit later, after hydration happens. My recommendations would be:
Regarding the prism code block fouc, we'd also want to use CSS variables for this. See FormidableLabs/prism-react-renderer#149 I guess one issue is enough, so let's close in favor of the existing one: #7986 |
Summary: See facebook/docusaurus#9629 We use prism to render the code for the inline editor. Prism renders colors to style directly, and the color chosen is dendent on a setting that may not be available at SSR time. This adds an SSR-specific representation of the code, missing some of the nuances in token colorization. This adds a little bit of jank compared to perfect SSR, but fixs cases where the mode is incorrect, and is a lot less jank then the more generic solution used by theme-live-codeblock of keeping the rendering of the opposite color until rehydration. Differential Revision: D52163722
Summary: Pull Request resolved: #1519 See facebook/docusaurus#9629 We use prism to render the code for the inline editor. Prism renders colors to style directly, and the color chosen is dependent on a setting that may not be available at SSR time. This adds an SSR-specific representation of the code, missing some of the nuances in token colorization (similar to facebook/docusaurus#7373). This adds a little bit of jank compared to perfect SSR, but fixes cases where the mode is incorrect, and is a lot less jank then the more generic solution used by theme-live-codeblock of keeping the rendering of the opposite color until rehydration. Preview: https://yoga-website-next-git-fork-nickgerleman-exp-2f8171-fbopensource.vercel.app/ Reviewed By: yungsters Differential Revision: D52163722 fbshipit-source-id: 312dc52134f0084d40f78147190151700ee10ff7
I've solved this problem by using const { colorMode } = useColorMode();
const rendersRef = useRef(1);
useEffect(() => {
// eslint-disable-next-line no-undef
const localStorageColorMode = localStorage.getItem('theme');
if (rendersRef.current === 1 && localStorageColorMode) {
// eslint-disable-next-line no-undef, @typescript-eslint/no-unsafe-member-access
document.querySelector('.invert').style.filter = localStorageColorMode === 'dark' ? 'invert(1)' : 'none';
}
rendersRef.current += 1;
}, [colorMode]); |
@finom this looks like a bad solution leading to FOUC. You don't want to wait for React hydration to invert the image, you want it to be displayed inverted as soon as possible, even if JS is fully disabled. Try our ThemedImage component instead: https://docusaurus.io/docs/markdown-features/assets#themed-images |
Have you read the Contributing Guidelines on issues?
Prerequisites
npm run clear
oryarn clear
command.rm -rf node_modules yarn.lock package-lock.json
and re-installing packages.Description
I have a website which relies on the
usePrismTheme()
hook, relying onuseColorMode()
. The website has an interactive code example (very similar in both form and code to the one provided by Docusaurus itself).The site is dark mode by default, but may be set to light mode. When I start the website, after previously setting light mode, everything looks corect when I start via development server, but if I do a build, the code relying on the usePrismTheme() hook shows the incorrect theme.
When I debugged this, it looks like:
useColorMode
, from first client render, has a color mode of "light"I found Docusaurus itself has a hack to get around this:
docusaurus/packages/docusaurus-theme-live-codeblock/src/theme/Playground/index.tsx
Line 78 in 61116e2
But this causes a black to white (or white to black) flash during hydration which is pretty jarring if the UI is shown above the fold.
This seems like a more general issue, where anything relying on the hook might get a different value at client time compared to server time. Though I'm not exactly sure how this could be cleanly solved without doing SSR on both sets of color modes.
Reproducible demo
https://github.com/facebook/yoga/tree/main/website-next
Steps to reproduce
yarn start
(works correctly)yarn build
(does not show correctly)Expected behavior
Light mode should use light scheme in prism editor
Actual behavior
Shows dark theme
Your environment
Self-service
The text was updated successfully, but these errors were encountered: