在反应中呈现页面之前从本地存储中获取主题

Grab theme from local storage before page is rendered in react

我正在构建一个带有 React 的小型 Web 应用程序,并且还包括一个 ThemeSwitcher 组件。该组件包含视觉方面,即切换,以及用于切换主题的脚本和用于访问本地存储的脚本。 ThemeSwitcher 组件然后被导入到 Header 组件中,而 Header 组件又被导入到 index.js

从深色主题(默认)切换到浅色主题时,此信息将保存到本地存储:

let currentTheme = "dark-theme";

function switchTheme() {
        const body = document.querySelector("body");
        const transitionChecker = document.querySelector("#theme-selector");
    
        body.classList.add("transition");
        body.classList.toggle("light-theme");
        transitionChecker.addEventListener("transitionend", () => {
            body.classList.remove("transition");
        });
        currentTheme === "dark-theme"
            ? (currentTheme = "light-theme")
            : (currentTheme = "dark-theme");
    
        localStorage.setItem("storedTheme", currentTheme);
    }

我在页面加载时使用以下方法访问此值:

window.addEventListener("load", function () {
    let storedTheme = localStorage.getItem("storedTheme");
    if (storedTheme === "light-theme") switchTheme();
});

这或多或少符合预期。但是,在页面加载时,深色主题会显示一瞬间,然后切换到浅色主题。

有什么方法可以在页面渲染之前抓取预期的主题以避免默认主题闪烁?

所以经过一番尝试,我相信有一个适合我的解决方案。我基本上只是把它放在 App.js 的开头(在 index.js 中呈现)就在声明实际组件之前:

//get stored theme right at the beginning
let currentTheme = localStorage.getItem("storedTheme");
if (!currentTheme) currentTheme = "dark-theme"; // if no theme was stored, set to default --> dark-theme

document.querySelector("body").classList.add(currentTheme);

我是如何得出这个解决方案的:

  • 我开始使用 create-react-app,所以切换到 Next.js 不是一个选择
  • 用 setTimeOut 尝试了一些东西,但无法让它工作
  • 尝试使用useEffect(),但这仍然让深色主题闪烁 通过如果先前选择的浅色主题
  • 将代码移到实际的 App 组件之外,但仍然 将其定位在 App.js 内有效。

switchTheme() 也被移动到 App.js 并位于最后。

不确定这是否是一个合适的解决方案,或者它是否只是给浏览器额外的一瞬间,以便在实际呈现之前获取存储的主题。但这对我有用。