Skip to content

Commit

Permalink
Merge pull request #12 from react18-tools/fix-supress-hydration-warning
Browse files Browse the repository at this point in the history
refactor: supressHydrationWarning and improve readability
  • Loading branch information
mayank1513 committed Jun 17, 2024
2 parents 8d9e02e + e7de9d5 commit fb87db3
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 18 deletions.
1 change: 1 addition & 0 deletions examples/nextjs/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
14 changes: 11 additions & 3 deletions examples/nextjs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
{
"exclude": ["node_modules"],
"exclude": [
"node_modules"
],
"extends": "@repo/typescript-config/nextjs.json",
"compilerOptions": {
"outDir": "dist",
"plugins": [
{
"name": "next"
}
]
],
"strictNullChecks": true
},
"include": ["src", "next.config.js", "next-env.d.ts", ".next/types/**/*.ts"]
"include": [
"src",
"next.config.js",
"next-env.d.ts",
".next/types/**/*.ts"
]
}
6 changes: 6 additions & 0 deletions lib/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# nextjs-darkmode

## 1.0.2

### Patch Changes

- 722eeae: Supress Hydration Warning

## 1.0.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "nextjs-darkmode",
"author": "Mayank Kumar Chaudhari <https://mayank-chaudhari.vercel.app>",
"private": false,
"version": "1.0.1",
"version": "1.0.2",
"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",
"license": "MPL-2.0",
"main": "./dist/index.js",
Expand Down
4 changes: 2 additions & 2 deletions lib/src/client/core/core.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { act, cleanup, fireEvent, render, renderHook } from "@testing-library/react";
import { afterEach, beforeEach, describe, test } from "vitest";
import { Core, s } from "./core";
import { Core, noFOUCScript } from "./core";
import { useMode } from "../../hooks";
import { DARK, LIGHT } from "../../constants";

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

beforeEach(() => {
s(STORAGE_KEY);
noFOUCScript(STORAGE_KEY);
render(<Core />);
});

Expand Down
31 changes: 25 additions & 6 deletions lib/src/client/core/core.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { DARK, LIGHT } from "../../constants";
import { ColorSchemePreference, ResolvedScheme, Store, useStore } from "../../utils";
import { useEffect } from "react";
import { ColorSchemePreference, ResolvedScheme, useStore } from "../../utils";
import { memo, useEffect } from "react";

declare global {
// skipcq: JS-0102, JS-0239
var u: (mode: ColorSchemePreference, systemMode: ResolvedScheme) => void;
// skipcq: JS-0102, JS-0239
var m: MediaQueryList;
}

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

interface ScriptProps {
/** nonce */
n?: string;
/** storageKey */
k: string;
}

/** Avoid rerender of script */
const Script = memo(({ n, k }: ScriptProps) => (
<script
suppressHydrationWarning
// skipcq: JS-0440
dangerouslySetInnerHTML={{ __html: `(${noFOUCScript.toString()})('${k}')` }}
nonce={n}
/>
));

export interface CoreProps {
/** themeTransition: force apply CSS transition property to all the elements during theme switching. E.g., `all .3s`
* @defaultValue 'none'
Expand Down Expand Up @@ -70,7 +89,7 @@ const modifyTransition = (themeTransition = "none", nonce = "") => {
*/
export const Core = ({ t, nonce, k = "o" }: CoreProps) => {
// handle client side exceptions when script is not run. <- for client side apps like vite or CRA
if (typeof window !== "undefined" && !window.m) s(k);
if (typeof window !== "undefined" && !window.m) noFOUCScript(k);

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

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

return <script dangerouslySetInnerHTML={{ __html: `(${s.toString()})('${k}')` }} nonce={nonce} />;
return <Script {...{ n: nonce, k }} />;
};
6 changes: 3 additions & 3 deletions lib/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ColorSchemePreference } from "./utils";
import { ColorSchemePreference, ResolvedScheme } from "./utils";

export const SYSTEM: ColorSchemePreference = "system";
export const DARK: ColorSchemePreference = "dark";
export const LIGHT: ColorSchemePreference = "";
export const DARK: ResolvedScheme = "dark";
export const LIGHT: ResolvedScheme = "";

export const modes: ColorSchemePreference[] = [SYSTEM, DARK, LIGHT];
2 changes: 1 addition & 1 deletion lib/src/hooks/use-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const useMode = (): UseModeYeild => {
return {
mode,
systemMode,
resolvedMode: (mode === SYSTEM ? systemMode : mode) as ResolvedScheme, // resolvedMode is the actual mode that will be used
resolvedMode: (mode === SYSTEM ? systemMode : mode) as ResolvedScheme,
setMode,
};
};
2 changes: 1 addition & 1 deletion lib/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface Store {
/** local abstaction of RGS to avoid multiple imports */
export const useStore = () =>
useRGS<Store>("ndm", () => {
if (typeof document === "undefined") return { m: SYSTEM, s: DARK as ResolvedScheme };
if (typeof document === "undefined") return { m: SYSTEM, s: DARK };
const el = document.documentElement;
return {
m: (el.getAttribute("data-m") ?? SYSTEM) as ColorSchemePreference,
Expand Down
7 changes: 7 additions & 0 deletions packages/shared/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @repo/shared

## 0.0.10

### Patch Changes

- Updated dependencies [722eeae]
- [email protected]

## 0.0.9

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@repo/shared",
"version": "0.0.9",
"version": "0.0.10",
"private": true,
"sideEffects": false,
"main": "./dist/index.js",
Expand Down

0 comments on commit fb87db3

Please sign in to comment.