-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
75 lines (67 loc) · 2.08 KB
/
index.ts
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
//@ts-check
import { useState, useEffect, useRef, useCallback } from "react"
function cloneDeep(obj) {
return JSON.parse(JSON.stringify(obj))
}
function isEqual(a,b) {
if(typeof a!=typeof b) {
return false
}
if(typeof a=='object' && typeof b=='object') {
if (Object.keys(a).length!=Object.keys(b).length) return false
}
return JSON.stringify(a)==JSON.stringify(b)
}
interface a{
updateStore:()=>void
useRerenderIfChange:(callback)=>void
}
export function newStore<T>(state:T):(a & T) {
//@ts-ignore
var Store:(a & T)=state
var callbacks = {}
var callbacksNextAvailableKey = 0
function updateStoreNow() {
scheduled=false
for (var i in callbacks) {
callbacks[i]()
}
}
var scheduled=false
function Schedule(){
if(scheduled) return
scheduled=true
setTimeout(updateStoreNow,0)
}
/**
* @example useRerenderIfChange((store) => [store.scale, store.othervalue])
* @param callback {(store:Store)=>void}
*/
Store.useRerenderIfChange=function(callback) {
var [_, setMeToRerender] = useState(0)
var callbacksKeyRef = useRef(callbacksNextAvailableKey++)
/** The array from the user. Cloned so new changes will not be there */
var cloned = useCallback(()=>cloneDeep(callback(Store)))
var lastValueRef = useRef(cloned)
useEffect(() => {
// When object mount, add a function to the callbacks, to change if the value changes
// it will trigged by the "updateStore below"
callbacks[callbacksKeyRef.current] = () => {
var currentValue = callback(Store) // The new array of values calculated from the store
if (!isEqual(currentValue, lastValueRef.current)) {
lastValueRef.current = cloneDeep(currentValue) // Update the old array.
setMeToRerender((prev) => prev + 1) // Rerender the objects
}
}
return () => {
// When object unmount we don't need this callback any more.
delete callbacks[callbacksKeyRef.current]
}
}, [])
return lastValueRef.current
}
Store.updateStore=function() {
Schedule()
}
return Store
}