Skip to content

Commit fb87db3

Browse files
authored
Merge pull request #12 from react18-tools/fix-supress-hydration-warning
refactor: supressHydrationWarning and improve readability
2 parents 8d9e02e + e7de9d5 commit fb87db3

File tree

11 files changed

+59
-18
lines changed

11 files changed

+59
-18
lines changed

examples/nextjs/next-env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3+
/// <reference types="next/navigation-types/compat/navigation" />
34

45
// NOTE: This file should not be edited
56
// see https://nextjs.org/docs/basic-features/typescript for more information.

examples/nextjs/tsconfig.json

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
{
2-
"exclude": ["node_modules"],
2+
"exclude": [
3+
"node_modules"
4+
],
35
"extends": "@repo/typescript-config/nextjs.json",
46
"compilerOptions": {
57
"outDir": "dist",
68
"plugins": [
79
{
810
"name": "next"
911
}
10-
]
12+
],
13+
"strictNullChecks": true
1114
},
12-
"include": ["src", "next.config.js", "next-env.d.ts", ".next/types/**/*.ts"]
15+
"include": [
16+
"src",
17+
"next.config.js",
18+
"next-env.d.ts",
19+
".next/types/**/*.ts"
20+
]
1321
}

lib/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# nextjs-darkmode
22

3+
## 1.0.2
4+
5+
### Patch Changes
6+
7+
- 722eeae: Supress Hydration Warning
8+
39
## 1.0.1
410

511
### Patch Changes

lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "nextjs-darkmode",
33
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
44
"private": false,
5-
"version": "1.0.1",
5+
"version": "1.0.2",
66
"description": "Unleash the Power of React Server Components! Use dark/light mode on your site with confidence, without losing any advantages of React Server Components",
77
"license": "MPL-2.0",
88
"main": "./dist/index.js",

lib/src/client/core/core.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { act, cleanup, fireEvent, render, renderHook } from "@testing-library/react";
22
import { afterEach, beforeEach, describe, test } from "vitest";
3-
import { Core, s } from "./core";
3+
import { Core, noFOUCScript } from "./core";
44
import { useMode } from "../../hooks";
55
import { DARK, LIGHT } from "../../constants";
66

@@ -9,7 +9,7 @@ describe("theme-switcher", () => {
99
afterEach(cleanup);
1010

1111
beforeEach(() => {
12-
s(STORAGE_KEY);
12+
noFOUCScript(STORAGE_KEY);
1313
render(<Core />);
1414
});
1515

lib/src/client/core/core.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import { DARK, LIGHT } from "../../constants";
2-
import { ColorSchemePreference, ResolvedScheme, Store, useStore } from "../../utils";
3-
import { useEffect } from "react";
2+
import { ColorSchemePreference, ResolvedScheme, useStore } from "../../utils";
3+
import { memo, useEffect } from "react";
44

55
declare global {
6+
// skipcq: JS-0102, JS-0239
67
var u: (mode: ColorSchemePreference, systemMode: ResolvedScheme) => void;
8+
// skipcq: JS-0102, JS-0239
79
var m: MediaQueryList;
810
}
911

1012
/** function to be injected in script tag for avoiding FOUC */
11-
export const s = (storageKey: string) => {
13+
export const noFOUCScript = (storageKey: string) => {
1214
const [SYSTEM, DARK] = ["system", "dark"] as const;
1315
window.u = (mode: ColorSchemePreference, systemMode: ResolvedScheme) => {
1416
const resolvedMode = mode === SYSTEM ? systemMode : mode;
@@ -30,6 +32,23 @@ export const s = (storageKey: string) => {
3032
let media: MediaQueryList,
3133
updateDOM: (mode: ColorSchemePreference, systemMode: ResolvedScheme) => void;
3234

35+
interface ScriptProps {
36+
/** nonce */
37+
n?: string;
38+
/** storageKey */
39+
k: string;
40+
}
41+
42+
/** Avoid rerender of script */
43+
const Script = memo(({ n, k }: ScriptProps) => (
44+
<script
45+
suppressHydrationWarning
46+
// skipcq: JS-0440
47+
dangerouslySetInnerHTML={{ __html: `(${noFOUCScript.toString()})('${k}')` }}
48+
nonce={n}
49+
/>
50+
));
51+
3352
export interface CoreProps {
3453
/** themeTransition: force apply CSS transition property to all the elements during theme switching. E.g., `all .3s`
3554
* @defaultValue 'none'
@@ -70,7 +89,7 @@ const modifyTransition = (themeTransition = "none", nonce = "") => {
7089
*/
7190
export const Core = ({ t, nonce, k = "o" }: CoreProps) => {
7291
// handle client side exceptions when script is not run. <- for client side apps like vite or CRA
73-
if (typeof window !== "undefined" && !window.m) s(k);
92+
if (typeof window !== "undefined" && !window.m) noFOUCScript(k);
7493

7594
const [{ m: mode, s: systemMode }, setThemeState] = useStore();
7695

@@ -79,7 +98,7 @@ export const Core = ({ t, nonce, k = "o" }: CoreProps) => {
7998
[media, updateDOM] = [m, u];
8099
/** Updating media: prefers-color-scheme*/
81100
media.addEventListener("change", () =>
82-
setThemeState(state => ({ ...state, s: media.matches ? DARK : LIGHT }) as Store),
101+
setThemeState(state => ({ ...state, s: media.matches ? DARK : LIGHT })),
83102
);
84103
/** Sync the tabs */
85104
addEventListener("storage", (e: StorageEvent): void => {
@@ -93,5 +112,5 @@ export const Core = ({ t, nonce, k = "o" }: CoreProps) => {
93112
restoreTransitions();
94113
}, [systemMode, mode, t, nonce]);
95114

96-
return <script dangerouslySetInnerHTML={{ __html: `(${s.toString()})('${k}')` }} nonce={nonce} />;
115+
return <Script {...{ n: nonce, k }} />;
97116
};

lib/src/constants.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { ColorSchemePreference } from "./utils";
1+
import { ColorSchemePreference, ResolvedScheme } from "./utils";
22

33
export const SYSTEM: ColorSchemePreference = "system";
4-
export const DARK: ColorSchemePreference = "dark";
5-
export const LIGHT: ColorSchemePreference = "";
4+
export const DARK: ResolvedScheme = "dark";
5+
export const LIGHT: ResolvedScheme = "";
66

77
export const modes: ColorSchemePreference[] = [SYSTEM, DARK, LIGHT];

lib/src/hooks/use-mode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const useMode = (): UseModeYeild => {
2727
return {
2828
mode,
2929
systemMode,
30-
resolvedMode: (mode === SYSTEM ? systemMode : mode) as ResolvedScheme, // resolvedMode is the actual mode that will be used
30+
resolvedMode: (mode === SYSTEM ? systemMode : mode) as ResolvedScheme,
3131
setMode,
3232
};
3333
};

lib/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface Store {
1111
/** local abstaction of RGS to avoid multiple imports */
1212
export const useStore = () =>
1313
useRGS<Store>("ndm", () => {
14-
if (typeof document === "undefined") return { m: SYSTEM, s: DARK as ResolvedScheme };
14+
if (typeof document === "undefined") return { m: SYSTEM, s: DARK };
1515
const el = document.documentElement;
1616
return {
1717
m: (el.getAttribute("data-m") ?? SYSTEM) as ColorSchemePreference,

packages/shared/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @repo/shared
22

3+
## 0.0.10
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [722eeae]
8+
9+
310
## 0.0.9
411

512
### Patch Changes

0 commit comments

Comments
 (0)