diff --git a/package.json b/package.json index dc400b8..8779df4 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "lodash": "^4.17.21", "mobx": "^6.5.0", "mobx-react-lite": "^3.4.0", + "mobx-utils": "^6.0.5", "next": "^12.1.6", "next-compose-plugins": "^2.2.1", "next-plugin-graphql": "^0.0.2", diff --git a/stores/calculation/values/hooks.js b/stores/calculation/values/hooks.js index 1b14e57..54bf7c5 100644 --- a/stores/calculation/values/hooks.js +++ b/stores/calculation/values/hooks.js @@ -1,32 +1,20 @@ /* eslint-disable import/prefer-default-export */ -import { useEffect, useState } from 'react'; import { useStore } from 'stores/hooks'; import { useDebouncedCallback } from 'use-debounce'; const DEBOUNCE_DELAY = 350; export function useValue(valueName) { - const [localValue, setLocalValue] = useState(); const { $calculation } = useStore(); - /** @description subscribe to updates from store */ - useEffect(() => { - const unsubscribe = $calculation.$values.subscribe(valueName, (value) => setLocalValue(value)); - return unsubscribe; - }); + const storeValue = $calculation.$values.observeValue(valueName); - const setStoreValue = useDebouncedCallback( - (value) => $calculation.$values.setValue(valueName, value), - DEBOUNCE_DELAY - ); - - /** @description set local state value to global store */ - useEffect(() => { - setStoreValue(localValue); - }, [localValue, setStoreValue]); + const setStoreValue = useDebouncedCallback((value) => { + $calculation.$values.setValue(valueName, value); + }, DEBOUNCE_DELAY); return { - value: localValue, - setValue: (val) => setLocalValue(val), + value: storeValue, + setValue: setStoreValue, }; } diff --git a/stores/calculation/values/index.ts b/stores/calculation/values/index.ts index 2c49170..9da8b43 100644 --- a/stores/calculation/values/index.ts +++ b/stores/calculation/values/index.ts @@ -4,33 +4,29 @@ import type { Elements, ElementsTypes } from 'Components/Calculation/config/map'; import { getValueName } from 'Components/Calculation/config/map'; import { makeAutoObservable } from 'mobx'; -import type { Callback } from 'stores/subscribers'; -import SubscribersStore from 'stores/subscribers'; +import { computedFn } from 'mobx-utils'; import RootStore from '../../root'; import type { CalculationValues, Values, ValuesTypes } from './types'; export default class ValuesStore { root: RootStore; - $subscribers: SubscribersStore; - #values: CalculationValues = {}; + values: CalculationValues = {}; constructor(rootStore: RootStore) { makeAutoObservable(this); this.root = rootStore; - this.$subscribers = new SubscribersStore(); } hydrate = (initialValues: CalculationValues) => { - this.#values = initialValues; + this.values = initialValues; }; - subscribe = (valueName: Values, callback: Callback) => - this.$subscribers.subscribe({ name: valueName, callback }); - getValue(valueName: V) { - return this.#values[valueName]; + return this.values[valueName]; } + observeValue = computedFn((valueName: Values) => this.getValue(valueName)); + getValueByElement(elementName: E) { const valueName = getValueName(elementName); return this.getValue(valueName) as ElementsTypes[E] | undefined; @@ -44,29 +40,26 @@ export default class ValuesStore { }, {} as Pick); } - setValue(valueName: V, value: ValuesTypes[V]) { - this.#values[valueName] = value; + setValue = (valueName: V, value: ValuesTypes[V]) => { + this.values[valueName] = value; + }; - /** call subscribers callback */ - this.$subscribers.runCallback(valueName, value); - } - - setValueOfElement(elementName: E, value: ElementsTypes[E]) { + setValueOfElement = (elementName: E, value: ElementsTypes[E]) => { const valueName = getValueName(elementName); this.setValue(valueName, value); - } + }; - setValues(values: CalculationValues, settings: { replace?: boolean }) { - if (settings?.replace) this.#values = values; - this.#values = Object.assign(this.#values, values); - } + setValues = (values: CalculationValues, settings: { replace?: boolean }) => { + if (settings?.replace) this.values = values; + this.values = Object.assign(this.values, values); + }; - clearValue(valueName: Values) { + clearValue = (valueName: Values) => { this.setValue(valueName, null); - } + }; - clearValueOfElement(elementName: Elements) { + clearValueOfElement = (elementName: Elements) => { const valueName = getValueName(elementName); this.clearValue(valueName); - } + }; } diff --git a/stores/subscribers.ts b/stores/subscribers.ts deleted file mode 100644 index 95f53a7..0000000 --- a/stores/subscribers.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable object-curly-newline */ -import { makeAutoObservable } from 'mobx'; - -export type Callback = (data: any) => void; -type Subscriber = { name: string; callback: Callback }; - -export default class SubscribersStore { - #subscribers = new Set(); - - constructor() { - makeAutoObservable(this); - } - - subscribe = (subscriber: Subscriber) => { - this.#subscribers.add(subscriber); - return () => this.#subscribers.delete(subscriber); - }; - - runCallback(name: string, data: any) { - const callback = Array.from(this.#subscribers).find((x) => x.name === name); - if (callback) callback.callback(data); - } -} diff --git a/yarn.lock b/yarn.lock index d48b09f..9c25ea0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4029,6 +4029,11 @@ mobx-react-lite@^3.4.0: resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.0.tgz#d59156a96889cdadad751e5e4dab95f28926dfff" integrity sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ== +mobx-utils@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/mobx-utils/-/mobx-utils-6.0.5.tgz#0cce9afb07fbba1fb559f959f8cea1f44baa7252" + integrity sha512-QOduwicYedD4mwYZRl8+c3BalljFDcubg+PUGqBkn8tOuBoj2q7GhjXBP6JXM9J+Zh+2mePK8IoToeLfqr3Z/w== + mobx@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.5.0.tgz#dc2d028b1882737f6e813fc92454381e438b7ad3"