Skip to content

Values derived from useColorMode() can be stale when rendering in prod mode #7986

@fvsch

Description

@fvsch

Have you read the Contributing Guidelines on issues?

Prerequisites

  • I'm using the latest version of Docusaurus.
  • I have tried the npm run clear or yarn clear command.
  • I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • I have tried creating a repro with https://new.docusaurus.io.
  • I have read the console error message carefully (if applicable).

Description

The value returned by the useColorMode hook from @docusaurus/theme-common seems to have a strange behavior when:

  1. Building for production and/or using React in prod mode (npm run build && npm run serve).
  2. window.localStorage.theme is 'dark' while the themeConfig.colorMode.defaultMode value is 'light', or window.localStorage.theme is 'light' while the themeConfig.colorMode.defaultMode value is 'dark'.

Then trying to use the colorMode value set the value of DOM attributes ends up generating a DOM with incorrect attribute values:

import { useColorMode } from "@docusaurus/theme-common";
import React from "react";

export default function ColorModeTest() {
  const { colorMode } = useColorMode();
  return (
    <div title={colorMode}>{colorMode}</div>
  );
}

In the conditions described above, if the themeConfig.colorMode.defaultMode value is 'light' and the localStorage.theme value is 'dark':

  1. The generated HTML will be: <div title="light">light</div>
  2. The hydrated DOM will be: <div title="light">dark</div>

This is particularly troublesome when you have UI components that support both dark and light themes and rely on HTML attributes to set the correct color theme on the component itself (e.g. in order to display a light component in a dark context for visual emphasis).

Reproducible demo

https://github.com/fvsch/docusaurus-use-color-mode-stale-value

Steps to reproduce

  1. Check out https://github.com/fvsch/docusaurus-use-color-mode-stale-value
  2. Install dependencies, build for prod and serve that build: npm install && npm run build && npm run serve
  3. The home page of the demo should be using a light theme.
  4. Click the theme switching button on the top right to switch to the dark theme.
  5. Reload the page.

Expected behavior

The values derived from the colorMode, whether they're text nodes or attribute nodes, should be in sync and reflect the localStorage.theme value.

In the last step, the visual result should be:

dev-mode-3-localstorage-theme-dark

Actual behavior

Attribute values that are derived from the colorMode value seem to be outdated.

In the last step, the visual result is:

prod-mode-3-localstorage-theme-dark

Your environment

Self-service

  • I'd be willing to fix this bug myself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugAn error in the Docusaurus core causing instability or issues with its executiondifficulty: intermediateIssues that are medium difficulty level, e.g. moderate refactoring with a clear test plan.domain: themeRelated to the default theme components

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions