81 lines
1.9 KiB
JavaScript
81 lines
1.9 KiB
JavaScript
import _ from 'lodash';
|
|
|
|
import { isValueEqual } from '../common';
|
|
import { flatPathGenerator } from './common';
|
|
|
|
|
|
export const createStore = (initialState) => {
|
|
let state = initialState;
|
|
|
|
const listeners = new Set();
|
|
const gen = flatPathGenerator('/');
|
|
const pathListeners = new Set();
|
|
|
|
// Exposed functions
|
|
// Don't attempt to manipulate the state directly.
|
|
const getState = () => state;
|
|
const setState = (nextState) => {
|
|
const prevState = state;
|
|
state = _.clone(nextState);
|
|
|
|
if (isValueEqual(state, prevState)) return;
|
|
|
|
listeners.forEach((listener) => {
|
|
listener();
|
|
});
|
|
|
|
const changeMemo = new Map();
|
|
|
|
pathListeners.forEach((pathListener) => {
|
|
const [ path, listener ] = pathListener;
|
|
const flatPath = gen.flatPath(path);
|
|
|
|
if (!changeMemo.has(flatPath)) {
|
|
const pathNextValue =
|
|
flatPath == '' ? nextState : _.get(nextState, path, undefined);
|
|
const pathPrevValue =
|
|
flatPath == '' ? prevState : _.get(prevState, path, undefined);
|
|
|
|
changeMemo.set(flatPath, [
|
|
isValueEqual(pathNextValue, pathPrevValue),
|
|
pathNextValue,
|
|
pathPrevValue,
|
|
]);
|
|
}
|
|
|
|
const [isSame, pathNextValue, pathPrevValue] = changeMemo.get(flatPath);
|
|
|
|
if (!isSame) {
|
|
listener(pathNextValue, pathPrevValue);
|
|
}
|
|
});
|
|
};
|
|
const get = (path = []) => (_.get(state, path));
|
|
const set = (arg) => {
|
|
let nextState = _.isFunction(arg) ? arg(_.cloneDeep(state)) : arg;
|
|
setState(nextState);
|
|
};
|
|
const subscribe = (listener) => {
|
|
listeners.add(listener);
|
|
return () => listeners.delete(listener);
|
|
};
|
|
const subscribeForPath = (path, listner) => {
|
|
const data = [path, listner];
|
|
|
|
pathListeners.add(data);
|
|
|
|
return () => {
|
|
return pathListeners.delete(data);
|
|
};
|
|
};
|
|
|
|
return {
|
|
getState,
|
|
setState,
|
|
get,
|
|
set,
|
|
subscribe,
|
|
subscribeForPath,
|
|
};
|
|
};
|