Skip to content

Commit

Permalink
🐛 fix: 修正 matchBrowserPrefer 在 SSR 下无法正常使用的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Mar 14, 2023
1 parent f80ca99 commit 660a338
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 13 deletions.
8 changes: 3 additions & 5 deletions src/context/ThemeModeContext.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { createContext } from 'react';

import { ThemeAppearance, ThemeContextState } from '@/types';

const matchThemeMode = (mode: ThemeAppearance) =>
matchMedia && matchMedia(`(prefers-color-scheme: ${mode})`);
import { ThemeContextState } from '@/types';
import { matchBrowserPrefers } from '@/utils/matchBrowserPrefers';

export const ThemeModeContext = createContext<ThemeContextState>({
appearance: 'light',
isDarkMode: false,
themeMode: 'light',
browserPrefers: matchThemeMode('dark')?.matches ? 'dark' : 'light',
browserPrefers: matchBrowserPrefers('dark')?.matches ? 'dark' : 'light',
});
14 changes: 6 additions & 8 deletions src/factories/createThemeProvider/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,25 @@ import { FC, memo, ReactNode, useEffect, useLayoutEffect, useMemo, useState } fr

import { ThemeModeContext } from '@/context';
import { BrowserPrefers, ThemeAppearance, ThemeMode, UseTheme } from '@/types';
import { matchBrowserPrefers } from '@/utils/matchBrowserPrefers';

let darkThemeMatch: MediaQueryList;

const matchThemeMode = (mode: ThemeAppearance) =>
matchMedia && matchMedia(`(prefers-color-scheme: ${mode})`);

const ThemeObserver: FC<{
themeMode: ThemeMode;
setAppearance: (value: ThemeAppearance) => void;
setBrowserPrefers: (value: BrowserPrefers) => void;
}> = ({ themeMode, setAppearance, setBrowserPrefers }) => {
const matchBrowserTheme = () => {
if (matchThemeMode('dark').matches) {
if (matchBrowserPrefers('dark').matches) {
setAppearance('dark');
} else {
setAppearance('light');
}
};

const updateBrowserTheme = () => {
if (matchThemeMode('dark').matches) {
if (matchBrowserPrefers('dark').matches) {
setBrowserPrefers('dark');
} else {
setBrowserPrefers('light');
Expand All @@ -41,7 +39,7 @@ const ThemeObserver: FC<{
setTimeout(matchBrowserTheme, 1);

if (!darkThemeMatch) {
darkThemeMatch = matchThemeMode('dark');
darkThemeMatch = matchBrowserPrefers('dark');
}
darkThemeMatch.addEventListener('change', matchBrowserTheme);

Expand All @@ -52,7 +50,7 @@ const ThemeObserver: FC<{

useEffect(() => {
if (!darkThemeMatch) {
darkThemeMatch = matchThemeMode('dark');
darkThemeMatch = matchBrowserPrefers('dark');
}

darkThemeMatch.addEventListener('change', updateBrowserTheme);
Expand Down Expand Up @@ -107,7 +105,7 @@ const ThemeSwitcher: FC<ThemeSwitcherProps> = memo(
});

const [browserPrefers, setBrowserPrefers] = useState<BrowserPrefers>(
matchThemeMode('dark')?.matches ? 'dark' : 'light',
matchBrowserPrefers('dark')?.matches ? 'dark' : 'light',
);

const [startObserver, setStartObserver] = useState(false);
Expand Down
9 changes: 9 additions & 0 deletions src/utils/matchBrowserPrefers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ThemeAppearance } from '@/types';

export const matchBrowserPrefers = (mode: ThemeAppearance): MediaQueryList => {
if (typeof window !== 'undefined') {
return matchMedia && matchMedia(`(prefers-color-scheme: ${mode})`);
}
// 针对 ssr 做特处
return { matches: false } as MediaQueryList;
};

0 comments on commit 660a338

Please sign in to comment.