This repository has been archived by the owner on Feb 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlib.js
110 lines (95 loc) · 2.47 KB
/
lib.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {
clearNode,
step,
createNode,
scopeBind,
createStore,
createEvent,
combine,
} from "effector";
const fAction = Symbol("f");
const fField = Symbol("f");
function createBoundEvent(event, scope) {
if (!scope) {
return event;
}
return scopeBind(event, {
scope,
});
}
// Copy-paste from effector-react =(
export function createBoundWatch(store, fn, scope) {
const seq = [step.run({ fn: (value) => fn(value) })];
if (scope) {
const node = createNode({ node: seq });
const id = store.graphite.id;
const scopeLinks = scope.additionalLinks;
const links = scopeLinks[id] || [];
scopeLinks[id] = links;
links.push(node);
return () => {
const idx = links.indexOf(node);
if (idx !== -1) links.splice(idx, 1);
clearNode(node);
};
} else {
const node = createNode({
node: seq,
parent: [store],
family: { owners: store },
});
return () => {
clearNode(node);
};
}
}
const reduxF = (config) => {
const $effectorStore = createStore(null);
const updateEffectorStore = createEvent();
$effectorStore.on(updateEffectorStore, (_, state) => state);
const effectorStores = [];
config.domain.onCreateStore((store) => effectorStores.push(store));
let effectorMegaStore = null;
if (effectorStores.length > 0) {
effectorMegaStore = combine(...effectorStores);
}
const updateEffectorStoreBound = createBoundEvent(
updateEffectorStore,
config.scope
);
function enhancer(creator) {
return function (reducer) {
function newReducer(state, action) {
// Just copy store to trigger re-renders
if (action.type === fAction) {
return { ...state, [fField]: (state[fField] ?? 0) + 1 };
}
return reducer(state, action);
}
const reduxStore = creator(newReducer);
// Sync from redux to effector
// on every dispatch
reduxStore.subscribe(() => {
updateEffectorStoreBound(reduxStore.getState());
});
// and for igaanitial state
updateEffectorStoreBound(reduxStore.getState());
// Sync from effector to redux
if (effectorMegaStore) {
createBoundWatch(
effectorMegaStore,
() => {
reduxStore.dispatch({ type: fAction, payload: null });
},
config.scope
);
}
return reduxStore;
};
}
return {
enhancer,
select: (selector) => $effectorStore.map(selector),
};
};
export { reduxF };