stores(values): use mobx-react-lite for hook

This commit is contained in:
Chika 2022-05-14 15:01:15 +03:00
parent 951b847a8d
commit 1cf69a122a
5 changed files with 31 additions and 67 deletions

View File

@ -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",

View File

@ -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,
};
}

View File

@ -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<V extends Values>(valueName: V) {
return this.#values[valueName];
return this.values[valueName];
}
observeValue = computedFn((valueName: Values) => this.getValue(valueName));
getValueByElement<E extends Elements>(elementName: E) {
const valueName = getValueName(elementName);
return this.getValue(valueName) as ElementsTypes[E] | undefined;
@ -44,29 +40,26 @@ export default class ValuesStore {
}, {} as Pick<CalculationValues, typeof valuesNames[number]>);
}
setValue<V extends Values>(valueName: V, value: ValuesTypes[V]) {
this.#values[valueName] = value;
setValue = <V extends Values>(valueName: V, value: ValuesTypes[V]) => {
this.values[valueName] = value;
};
/** call subscribers callback */
this.$subscribers.runCallback(valueName, value);
}
setValueOfElement<E extends Elements>(elementName: E, value: ElementsTypes[E]) {
setValueOfElement = <E extends Elements>(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);
}
};
}

View File

@ -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<Subscriber>();
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);
}
}

View File

@ -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"