@ehsaneha/react-observable-store
Version:
This is an extension of the `@ehsaneha/observable-store` library specifically tailored for React applications inspired by `zustand` library.
106 lines (105 loc) • 4.39 kB
JavaScript
import React from "react";
import { ObservableStoreClass, } from "@ehsaneha/observable-store";
import isEqual from "lodash.isequal";
export * from "./types";
// export const isInComponent = () => {
// let _result = false;
// try {
// React.useRef(null);
// _result = true;
// } catch (_) {}
// return _result;
// };
export class ReactObservableStoreClass extends ObservableStoreClass {
constructor() {
// onChange = (
// observer: Observer<S | undefined>,
// deps?: ObserverDeps<S | undefined>
// ) => {
// if (isInComponent()) {
// React.useEffect(() => {
// const obj = { observer, deps };
// this.addObserver(obj);
// return () => this.removeObserver(obj);
// }, []);
// } else {
// this.onChange(observer, deps);
// }
// };
super(...arguments);
this.useOnChange = (observer, deps) => {
React.useEffect(() => {
// const obj = { observer, deps };
// this.addObserver(obj);
// return () => this.removeObserver(obj);
const removeObserver = this.onChange(observer, deps);
return () => removeObserver();
}, []);
};
this.useGet = (func) => {
const [state] = this.useState(func);
return state;
};
this.useState = (func, useEffectDeps = [], onChangeDeps) => {
const [state, _setState] = React.useState(func ? func(this.get(), undefined, undefined) : this.get());
const _getState = (storeState, localPrevState) => {
const _newLocalState = func
? func(storeState, localPrevState, this.get())
: storeState;
return isEqual(_newLocalState, localPrevState)
? localPrevState
: _newLocalState;
};
this.useOnChange((v) => _setState((s) => _getState(v, s)), onChangeDeps);
React.useEffect(() => {
_setState((s) => _getState(this.get(), s));
}, useEffectDeps);
return [state, this.set, _setState];
};
// useSubStore = <S, TActions extends Actions, SubState>(
// subFunc?: (state: S) => SubState,
// actions?: CreateActionsFunc<S | undefined, TActions>
// ): Store<SubState, TActions> => {
// const themeStore = useStore({
// themeColor: _currentUserContext.userStore.get()?.themeColor ?? "#11296b",
// bgImage: _currentUserContext.userStore.get()?.bgImage ?? null,
// });
// _currentUserContext.userStore.useOnChange(
// (user) => {
// themeStore.set({
// themeColor: user?.themeColor ?? "#11296b",
// bgImage: user?.bgImage ?? null,
// });
// },
// (s) => [s?.themeColor, s?.bgImage]
// );
// };
// useBind = <S, TActions extends Actions, SubState>(
// func?: (state: S) => void,
// actions?: CreateActionsFunc<S | undefined, TActions>
// ): Store<SubState, TActions> => {
// const getCanSubmit = () => {
// return (
// submitErrorsStore.get() === null &&
// isEmpty(localErrorsStore.get()) &&
// (allowInitSubmit ||
// stringify(initData()) !== stringify(dataStore.get()))
// );
// };
// const canSubmit = () => {
// canSubmitStore.set(getCanSubmit());
// };
// const canSubmitStore = useStore(getCanSubmit());
// submitErrorsStore.useOnChange(canSubmit);
// localErrorsStore.useOnChange(canSubmit);
// dataStore.useOnChange(canSubmit);
// };
}
}
export const createStore = (initState, actions) => {
const _store = new ReactObservableStoreClass(initState);
return Object.assign(_store, actions === null || actions === void 0 ? void 0 : actions(Object.assign({}, _store)));
};
export const useStore = (initState, actions) => {
return React.useMemo(() => createStore(initState, actions), []);
};