Skip to content

Commit 06f3a26

Browse files
committed
fix: reset value on hydration
1 parent e356bc7 commit 06f3a26

File tree

7 files changed

+93
-128
lines changed

7 files changed

+93
-128
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
"@debbl/ahooks": "^0.1.0",
1515
"@monaco-editor/react": "^4.6.0",
1616
"highlight.js": "^11.9.0",
17+
"jotai": "^2.8.4",
1718
"monaco-editor": "^0.50.0",
1819
"next": "^14.2.4",
1920
"react": "^18.3.1",
20-
"react-dom": "^18.3.1",
21-
"zustand": "^4.5.4"
21+
"react-dom": "^18.3.1"
2222
},
2323
"devDependencies": {
2424
"@debbl/eslint-config": "^3.3.2",

pnpm-lock.yaml

+20-34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/layout.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import "~/styles/globals.css";
2+
import { Provider } from "jotai";
23
import nextConfig from "../../next.config.mjs";
34

45
const { basePath } = nextConfig;
@@ -18,7 +19,9 @@ export default function RootLayout({
1819
type="image/x-icon"
1920
/>
2021
</head>
21-
<body>{children}</body>
22+
<body>
23+
<Provider>{children}</Provider>
24+
</body>
2225
</html>
2326
);
2427
}

src/app/page.tsx

+27-42
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,34 @@ import type { DiffOnMount, Monaco } from "@monaco-editor/react";
33
import { DiffEditor } from "@monaco-editor/react";
44
import hljs from "highlight.js";
55
import { useRef } from "react";
6-
import { useLatest } from "@debbl/ahooks";
6+
import { useHydrated, useLatest } from "@debbl/ahooks";
77
import nextConfig from "../../next.config.mjs";
8-
import useMainStore from "~/store/useMainStore";
98
import Header from "~/components/Header";
109
import useTheme from "~/hooks/useTheme";
1110
import useToast from "~/hooks/useToast";
12-
import type { GetStoreState } from "~/types";
11+
import { useMainStore } from "~/store/useMainStore";
1312

1413
const { basePath } = nextConfig;
1514

16-
const selector = (s: GetStoreState<typeof useMainStore>) =>
17-
[
18-
{
19-
originalValue: s.originalValue,
20-
modifiedValue: s.modifiedValue,
21-
language: s.language,
22-
languages: s.languages,
23-
theme: s.theme,
24-
renderSideBySide: s.renderSideBySide,
25-
},
26-
{
27-
setLanguage: s.setLanguage,
28-
setLanguages: s.setLanguages,
29-
setOriginalValue: s.setOriginalValue,
30-
setModifiedValue: s.setModifiedValue,
31-
},
32-
] as const;
33-
3415
export default function Page() {
35-
const [
36-
{
37-
originalValue,
38-
modifiedValue,
39-
language,
40-
languages,
41-
theme,
42-
renderSideBySide,
43-
},
44-
{ setOriginalValue, setModifiedValue, setLanguage, setLanguages },
45-
] = useMainStore(selector);
16+
const {
17+
originalValue,
18+
modifiedValue,
19+
language,
20+
languages,
21+
theme,
22+
renderSideBySide,
23+
setOriginalValue,
24+
setModifiedValue,
25+
setLanguage,
26+
setLanguages,
27+
} = useMainStore();
4628

4729
useTheme();
4830
const { Toast, showToast } = useToast();
4931
const monacoRef = useRef<Monaco>();
5032
const languageRef = useLatest(language);
33+
const { isHydrated } = useHydrated();
5134

5235
const handleOnMount: DiffOnMount = (editor, monaco) => {
5336
monacoRef.current = monaco;
@@ -89,16 +72,18 @@ export default function Page() {
8972
<Header monaco={monacoRef.current} />
9073

9174
<main className="size-full">
92-
<DiffEditor
93-
options={{
94-
originalEditable: true,
95-
renderSideBySide,
96-
}}
97-
onMount={handleOnMount}
98-
height="100%"
99-
theme={theme}
100-
language={language}
101-
/>
75+
{isHydrated && (
76+
<DiffEditor
77+
options={{
78+
originalEditable: true,
79+
renderSideBySide,
80+
}}
81+
onMount={handleOnMount}
82+
height="100%"
83+
theme={theme}
84+
language={language}
85+
/>
86+
)}
10287
</main>
10388
</div>
10489
</>

src/components/Header.tsx

+11-22
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,23 @@ import closeFilled from "@iconify/icons-carbon/close-filled";
33

44
import type { Monaco } from "@monaco-editor/react";
55
import { useGitHubInfo, useHydrated } from "@debbl/ahooks";
6-
import useMainStore from "~/store/useMainStore";
7-
import type { GetStoreState, Theme } from "~/types";
6+
import type { Theme } from "~/types";
7+
import { useMainStore } from "~/store/useMainStore";
88

99
interface IProps {
1010
monaco?: Monaco;
1111
}
1212

13-
const selector = (s: GetStoreState<typeof useMainStore>) =>
14-
[
15-
{
16-
language: s.language,
17-
languages: s.languages,
18-
theme: s.theme,
19-
renderSideBySide: s.renderSideBySide,
20-
},
21-
{
22-
setLanguage: s.setLanguage,
23-
setLanguages: s.setLanguages,
24-
setTheme: s.setTheme,
25-
setRenderSideBySide: s.setRenderSideBySide,
26-
},
27-
] as const;
28-
2913
const Header = ({ monaco }: IProps) => {
30-
const [
31-
{ language, languages, theme, renderSideBySide },
32-
{ setLanguage, setTheme, setRenderSideBySide },
33-
] = useMainStore(selector);
14+
const {
15+
language,
16+
languages,
17+
theme,
18+
renderSideBySide,
19+
setLanguage,
20+
setTheme,
21+
setRenderSideBySide,
22+
} = useMainStore();
3423

3524
const { isHydrated } = useHydrated();
3625

src/hooks/useTheme.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { useEffect } from "react";
2-
import useMainStore from "~/store/useMainStore";
2+
import { useMainStore } from "~/store/useMainStore";
33

44
const useTheme = () => {
5-
const theme = useMainStore((s) => (s.theme === "vs-dark" ? "dark" : "light"));
5+
const { theme } = useMainStore();
66

77
useEffect(() => {
88
const html = document.querySelector("html");

src/store/useMainStore.ts

+27-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { create } from "zustand";
2-
import { persist } from "zustand/middleware";
31
import type { languages } from "monaco-editor/esm/vs/editor/editor.api";
2+
import { useAtom } from "jotai";
3+
import { atomWithStorage } from "jotai/utils";
4+
45
import type { Theme } from "~/types";
56

67
export interface MainStoreState {
@@ -23,28 +24,29 @@ export interface MainStoreActions {
2324
) => void;
2425
}
2526

26-
const useMainStore = create<MainStoreState & MainStoreActions>()(
27-
persist(
28-
(set) => ({
29-
originalValue: "",
30-
modifiedValue: "",
31-
language: "plaintext",
32-
languages: [],
33-
theme: "light",
34-
renderSideBySide: true,
35-
36-
setOriginalValue: (originalValue) => set({ originalValue }),
37-
setModifiedValue: (modifiedValue) => set({ modifiedValue }),
38-
setLanguage: (language) => set({ language }),
39-
setLanguages: (languages) => set({ languages }),
40-
setTheme: (theme) => set({ theme }),
41-
setRenderSideBySide: (renderSideBySide) => set({ renderSideBySide }),
42-
}),
43-
{
44-
name: "code-diff-main-store",
45-
version: 1,
46-
},
47-
),
27+
const useMainStoreAtom = atomWithStorage<MainStoreState>(
28+
"code-diff-main-store",
29+
{
30+
originalValue: "",
31+
modifiedValue: "",
32+
language: "plaintext",
33+
languages: [],
34+
theme: "light",
35+
renderSideBySide: true,
36+
},
4837
);
4938

50-
export default useMainStore;
39+
export function useMainStore() {
40+
const [state, set] = useAtom(useMainStoreAtom);
41+
42+
return {
43+
...state,
44+
setOriginalValue: (originalValue) => set((s) => ({ ...s, originalValue })),
45+
setModifiedValue: (modifiedValue) => set((s) => ({ ...s, modifiedValue })),
46+
setLanguage: (language) => set((s) => ({ ...s, language })),
47+
setLanguages: (languages) => set((s) => ({ ...s, languages })),
48+
setTheme: (theme) => set((s) => ({ ...s, theme })),
49+
setRenderSideBySide: (renderSideBySide) =>
50+
set((s) => ({ ...s, renderSideBySide })),
51+
} as MainStoreActions & MainStoreState;
52+
}

0 commit comments

Comments
 (0)