From 734df488539c87ab19b05ada29b9dfe33d9b372b Mon Sep 17 00:00:00 2001 From: L&H Date: Tue, 19 Dec 2023 15:02:54 +0800 Subject: [PATCH] chore: refactor react store --- apps/react-demo/src/app.tsx | 9 +++----- .../src/component/mobx/MobxSubmit.tsx | 4 ++-- .../src/component/mobx/MobxThemeSwitch.tsx | 6 +++-- .../src/component/mobx/MobxThemeSwitch2.tsx | 23 ------------------- .../react-demo/src/component/mobx/Section.tsx | 2 +- apps/react-demo/src/context.ts | 5 ---- apps/react-demo/src/store/app/submit.store.ts | 8 ++++--- apps/react-demo/src/store/app/ui.store.ts | 8 ++++--- apps/react-demo/src/store/context.ts | 3 +++ apps/react-demo/src/store/defineStore.ts | 20 ++++++++++++++++ .../src/store/global/theme.store.ts | 8 ++++++- apps/react-demo/src/store/root.store.ts | 10 -------- 12 files changed, 50 insertions(+), 56 deletions(-) delete mode 100644 apps/react-demo/src/component/mobx/MobxThemeSwitch2.tsx delete mode 100644 apps/react-demo/src/context.ts create mode 100644 apps/react-demo/src/store/context.ts create mode 100644 apps/react-demo/src/store/defineStore.ts delete mode 100644 apps/react-demo/src/store/root.store.ts diff --git a/apps/react-demo/src/app.tsx b/apps/react-demo/src/app.tsx index ac91c4a..4c887a1 100644 --- a/apps/react-demo/src/app.tsx +++ b/apps/react-demo/src/app.tsx @@ -1,24 +1,21 @@ import './style/global.less'; import React from 'react'; import { createRoot } from 'react-dom/client'; -import { RootStore } from './store/root.store'; import { JetbrainsLogo } from '@apex/svg-project'; -import { RootContext } from './context'; import { MobxThemeSwitch } from './component/mobx/MobxThemeSwitch'; -import { MobxThemeSwitch2 } from './component/mobx/MobxThemeSwitch2'; import { Section } from './component/mobx/Section'; +import { RootContext } from './store/context'; export function createReactApp(container: HTMLElement, node?: HTMLElement) { - const rootStore = new RootStore(); const root = createRoot(container); + const rootValue = new Map(); root.render( - +

- , ); diff --git a/apps/react-demo/src/component/mobx/MobxSubmit.tsx b/apps/react-demo/src/component/mobx/MobxSubmit.tsx index 95891e1..bed3c52 100644 --- a/apps/react-demo/src/component/mobx/MobxSubmit.tsx +++ b/apps/react-demo/src/component/mobx/MobxSubmit.tsx @@ -1,14 +1,14 @@ -import { useStore } from '../../context'; import { observer } from 'mobx-react-lite'; import { Submit } from '../atom/Submit'; import { useCallback } from 'react'; +import { useSubmitStore } from '../../store/app/submit.store'; /** * @desc View with Store (Cannot reuse without same store) */ export const MobxSubmit = observer(() => { // App store (Mobx) - const { submitStore } = useStore(); + const submitStore = useSubmitStore(); const onClick = useCallback(() => { submitStore.toggle(); setTimeout(() => submitStore.toggle(), 3000); diff --git a/apps/react-demo/src/component/mobx/MobxThemeSwitch.tsx b/apps/react-demo/src/component/mobx/MobxThemeSwitch.tsx index 1cbfc9b..64aa296 100644 --- a/apps/react-demo/src/component/mobx/MobxThemeSwitch.tsx +++ b/apps/react-demo/src/component/mobx/MobxThemeSwitch.tsx @@ -1,15 +1,17 @@ import { observer } from 'mobx-react-lite'; import { useEffect } from 'react'; -import { themeStore } from '../../store/global/theme.store'; +import { useThemeStore } from '../../store/global/theme.store'; export const MobxThemeSwitch = observer(() => { + const themeStore = useThemeStore(); + useEffect(() => { document.body.dataset.theme = themeStore.theme; }, [themeStore.theme]); return (

- +

); }); diff --git a/apps/react-demo/src/component/mobx/MobxThemeSwitch2.tsx b/apps/react-demo/src/component/mobx/MobxThemeSwitch2.tsx deleted file mode 100644 index 94623b1..0000000 --- a/apps/react-demo/src/component/mobx/MobxThemeSwitch2.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { observer } from 'mobx-react-lite'; -import { useStore } from '../../context'; -import { useEffect } from 'react'; - -/** - * @desc Only demo - */ -export const MobxThemeSwitch2 = observer(() => { - /** - * Use ReactContext instead of import variable. - */ - const { themeStore } = useStore(); - - useEffect(() => { - document.body.dataset.theme = themeStore.theme; - }, [themeStore.theme]); - - return ( -

- -

- ); -}); diff --git a/apps/react-demo/src/component/mobx/Section.tsx b/apps/react-demo/src/component/mobx/Section.tsx index 16d78db..dfe8f36 100644 --- a/apps/react-demo/src/component/mobx/Section.tsx +++ b/apps/react-demo/src/component/mobx/Section.tsx @@ -11,7 +11,7 @@ export const Section = () => { {/* It's a memo component */} - {/* It's a pure react component */} + {/* It's a pure React component */} {/* DON'T USE THIS in Mobx, it's only a demo */} {/* Wrap it with Mobx.observer if you want to use it in mobx environment */} diff --git a/apps/react-demo/src/context.ts b/apps/react-demo/src/context.ts deleted file mode 100644 index bdf19e6..0000000 --- a/apps/react-demo/src/context.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext, useContext } from 'react'; -import { RootStore } from './store/root.store'; - -export const RootContext = createContext(null); -export const useStore = () => useContext(RootContext) as RootStore; diff --git a/apps/react-demo/src/store/app/submit.store.ts b/apps/react-demo/src/store/app/submit.store.ts index cfdbc37..719ca7a 100644 --- a/apps/react-demo/src/store/app/submit.store.ts +++ b/apps/react-demo/src/store/app/submit.store.ts @@ -1,13 +1,13 @@ import { makeAutoObservable } from 'mobx'; -import { RootStore } from '../root.store'; +import { defineStore } from '../defineStore'; /** * @desc App Store */ -export class SubmitStore { +class SubmitStore { submitted = false; - constructor(readonly rootStore: RootStore) { + constructor() { makeAutoObservable(this); } @@ -15,3 +15,5 @@ export class SubmitStore { this.submitted = !this.submitted; } } + +export const useSubmitStore = defineStore('submit', SubmitStore); diff --git a/apps/react-demo/src/store/app/ui.store.ts b/apps/react-demo/src/store/app/ui.store.ts index db580b2..fdbed8d 100644 --- a/apps/react-demo/src/store/app/ui.store.ts +++ b/apps/react-demo/src/store/app/ui.store.ts @@ -1,11 +1,13 @@ -import { RootStore } from '../root.store'; import { makeAutoObservable } from 'mobx'; +import { defineStore } from '../defineStore'; /** * @desc App Store */ -export class UiStore { - constructor(readonly rootStore: RootStore) { +class UiStore { + constructor() { makeAutoObservable(this); } } + +export const useUiStore = defineStore('ui', UiStore); diff --git a/apps/react-demo/src/store/context.ts b/apps/react-demo/src/store/context.ts new file mode 100644 index 0000000..7583b98 --- /dev/null +++ b/apps/react-demo/src/store/context.ts @@ -0,0 +1,3 @@ +import { createContext } from 'react'; + +export const RootContext = createContext | null>(null); diff --git a/apps/react-demo/src/store/defineStore.ts b/apps/react-demo/src/store/defineStore.ts new file mode 100644 index 0000000..0913e2a --- /dev/null +++ b/apps/react-demo/src/store/defineStore.ts @@ -0,0 +1,20 @@ +import { RootContext } from './context'; +import { useContext } from 'react'; + +export function defineStore InstanceType>(id: string, Ctor: T) { + return (injectedContext?: Map | null): InstanceType => { + const map = injectedContext || useContext(RootContext); + + if (!map) { + throw new Error('[defineStore] must be used within a Provider'); + } + + if (map.has(id)) { + return map.get(id) as InstanceType; + } else { + const instance = new Ctor(); + map.set(id, instance); + return instance; + } + }; +} diff --git a/apps/react-demo/src/store/global/theme.store.ts b/apps/react-demo/src/store/global/theme.store.ts index e5af169..10ef49f 100644 --- a/apps/react-demo/src/store/global/theme.store.ts +++ b/apps/react-demo/src/store/global/theme.store.ts @@ -1,4 +1,5 @@ import { makeAutoObservable } from 'mobx'; +import { defineStore } from '../defineStore'; /** * @desc Global Store (Singleton) @@ -15,4 +16,9 @@ class ThemeStore { } } -export const themeStore = new ThemeStore(); +/** + * Shared for Global Store + */ +const globalContextValue = new Map(); + +export const useThemeStore = () => defineStore('theme', ThemeStore)(globalContextValue); diff --git a/apps/react-demo/src/store/root.store.ts b/apps/react-demo/src/store/root.store.ts deleted file mode 100644 index f8535c6..0000000 --- a/apps/react-demo/src/store/root.store.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { UiStore } from './app/ui.store'; -import { themeStore } from './global/theme.store'; -import { SubmitStore } from './app/submit.store'; - -export class RootStore { - themeStore = themeStore; - - uiStore = new UiStore(this); - submitStore = new SubmitStore(this); -}