mirror of
https://github.com/massbug/judge4c.git
synced 2025-05-18 07:16:34 +00:00
refactor(problem-editor): replace Zustand store with useRef store
This commit is contained in:
parent
14bee1ade8
commit
8904e13a68
@ -1,110 +1,66 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type {
|
import {
|
||||||
EditorLanguage,
|
EditorLanguage,
|
||||||
EditorLanguageConfig,
|
type EditorLanguageConfig,
|
||||||
LanguageServerConfig,
|
type LanguageServerConfig,
|
||||||
Template,
|
type Template,
|
||||||
} from "@prisma/client";
|
} from "@prisma/client";
|
||||||
import type { editor } from "monaco-editor";
|
import { useStore } from "zustand";
|
||||||
import { createStore, StoreApi, useStore } from "zustand";
|
import { type ReactNode, createContext, useRef, useContext } from "react";
|
||||||
import { persist, createJSONStorage } from "zustand/middleware";
|
import { type ProblemStore, createProblemStore } from "@/stores/problem-store";
|
||||||
import type { MonacoLanguageClient } from "monaco-languageclient";
|
|
||||||
import { DEFAULT_EDITOR_LANGUAGE } from "@/config/editor-language";
|
|
||||||
import { createContext, PropsWithChildren, useContext, useState } from "react";
|
|
||||||
|
|
||||||
type ProblemEditorState = {
|
export type ProblemStoreApi = ReturnType<typeof createProblemStore>;
|
||||||
hydrated: boolean;
|
|
||||||
editor: editor.IStandaloneCodeEditor | null;
|
export const ProblemStoreContext = createContext<ProblemStoreApi | undefined>(
|
||||||
monacoLanguageClient: MonacoLanguageClient | null;
|
undefined
|
||||||
globalLang: EditorLanguage;
|
);
|
||||||
currentLang: EditorLanguage;
|
|
||||||
currentValue: string;
|
export interface ProblemStoreProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
problemId: string;
|
problemId: string;
|
||||||
templates: Template[];
|
templates: Template[];
|
||||||
editorLanguageConfigs: EditorLanguageConfig[];
|
editorLanguageConfigs: EditorLanguageConfig[];
|
||||||
languageServerConfigs: LanguageServerConfig[];
|
languageServerConfigs: LanguageServerConfig[];
|
||||||
};
|
}
|
||||||
|
|
||||||
type ProblemEditorActions = {
|
export const ProblemStoreProvider = ({
|
||||||
setHydrated: (value: boolean) => void;
|
|
||||||
setEditor: (editor: editor.IStandaloneCodeEditor) => void;
|
|
||||||
setMonacoLanguageClient: (client: MonacoLanguageClient | null) => void;
|
|
||||||
setGlobalLang: (lang: EditorLanguage) => void;
|
|
||||||
setCurrentLang: (lang: EditorLanguage) => void;
|
|
||||||
setCurrentValue: (value: string) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ProblemEditorStore = ProblemEditorState & ProblemEditorActions;
|
|
||||||
|
|
||||||
const ProblemEditorContext = createContext<StoreApi<ProblemEditorStore> | undefined>(undefined);
|
|
||||||
|
|
||||||
type ProblemEditorProviderProps = PropsWithChildren & {
|
|
||||||
problemId: string;
|
|
||||||
templates: Template[];
|
|
||||||
editorLanguageConfigs: EditorLanguageConfig[];
|
|
||||||
languageServerConfigs: LanguageServerConfig[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ProblemEditorProvider({
|
|
||||||
children,
|
children,
|
||||||
problemId,
|
problemId,
|
||||||
templates,
|
templates,
|
||||||
editorLanguageConfigs,
|
editorLanguageConfigs,
|
||||||
languageServerConfigs,
|
languageServerConfigs,
|
||||||
}: ProblemEditorProviderProps) {
|
}: ProblemStoreProviderProps) => {
|
||||||
const [store] = useState(() =>
|
const storeRef = useRef<ProblemStoreApi | null>(null);
|
||||||
createStore<ProblemEditorStore>()(
|
|
||||||
persist(
|
if (storeRef.current === null) {
|
||||||
(set) => ({
|
storeRef.current = createProblemStore({
|
||||||
hydrated: false,
|
hydrated: false,
|
||||||
editor: null,
|
editor: null,
|
||||||
monacoLanguageClient: null,
|
monacoLanguageClient: null,
|
||||||
globalLang: DEFAULT_EDITOR_LANGUAGE,
|
globalLang: EditorLanguage.c,
|
||||||
currentLang: DEFAULT_EDITOR_LANGUAGE,
|
currentLang: EditorLanguage.c,
|
||||||
currentValue: "",
|
currentValue: "",
|
||||||
problemId,
|
problemId,
|
||||||
templates,
|
templates,
|
||||||
editorLanguageConfigs,
|
editorLanguageConfigs,
|
||||||
languageServerConfigs,
|
languageServerConfigs,
|
||||||
setHydrated: (value) => set({ hydrated: value }),
|
});
|
||||||
setEditor: (editor) => set({ editor }),
|
}
|
||||||
setMonacoLanguageClient: (client) => set({ monacoLanguageClient: client }),
|
|
||||||
setGlobalLang: (lang) => set({ globalLang: lang }),
|
|
||||||
setCurrentLang: (lang) => set({ currentLang: lang }),
|
|
||||||
setCurrentValue: (value) => set({ currentValue: value }),
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
name: "problem-store",
|
|
||||||
storage: createJSONStorage(() => localStorage),
|
|
||||||
partialize: (state) => ({
|
|
||||||
globalLang: state.globalLang,
|
|
||||||
}),
|
|
||||||
onRehydrateStorage: () => {
|
|
||||||
return (state, error) => {
|
|
||||||
if (error) {
|
|
||||||
console.error("An error happened during hydration", error);
|
|
||||||
} else if (state) {
|
|
||||||
state.setHydrated(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProblemEditorContext.Provider value={store}>
|
<ProblemStoreContext.Provider value={storeRef.current}>
|
||||||
{children}
|
{children}
|
||||||
</ProblemEditorContext.Provider>
|
</ProblemStoreContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export function useProblemEditorStore<T>(selector: (state: ProblemEditorStore) => T) {
|
export const useProblemStore = <T,>(selector: (store: ProblemStore) => T): T => {
|
||||||
const context = useContext(ProblemEditorContext);
|
const problemStoreContext = useContext(ProblemStoreContext);
|
||||||
if (!context) {
|
|
||||||
throw new Error("ProblemEditorContext.Provider is missing.");
|
if (!problemStoreContext) {
|
||||||
|
throw new Error("useProblemStore must be used within ProblemStoreProvider");
|
||||||
}
|
}
|
||||||
return useStore(context, selector);
|
|
||||||
}
|
return useStore(problemStoreContext, selector);
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user