# Recoil 源码
# 手写一个 Recoil
import { useCallback, useEffect, useState } from "react";
interface Dissconnect {
disconnect: () => void;
}
// atom和selector的一个基类
export class Stateful<T> {
// 状态发生改变是通知, Set的类型是个函数
private listeners = new Set<(value: T) => void>();
constructor(protected value: T) {}
// 做一个快照,负责拿类型T
snapshot(): T {
return this.value;
}
// 订阅
public subscribe(callback: (value: T) => void): Dissconnect {
this.listeners.add(callback);
return {
disconnect: () => {
this.listeners.delete(callback);
},
};
}
// 通知所有的Listener更新
protected emit() {
console.log("提交更新");
// 这里的listener是所有的selector
for (const listener of Array.from(this.listeners)) {
listener(this.snapshot());
}
}
// 更新
protected update(value: T) {
console.log("this.value🍊", this);
if (this.value !== value) {
// 发现值不一样,就提交更新
this.value = value;
this.emit();
}
}
}
class Atom<T> extends Stateful<T> {
public setState(value: T) {
super.update(value);
}
}
// const charCountState = selector({
// key: 'charCountState', // unique ID (with respect to other atoms/selectors)
// get: ({get}) => {
// const text = get(textState);
// return text.length;
// },
// });
class Selector<V> extends Stateful<V> {
constructor(private readonly generate: SelectorGenerator<V>) {
// 得到的是({get}) => {
// const text = get(textState);
// return text.length;
// }
super(undefined as any);
this.value = generate({ get: (dep: Stateful<any>) => this.addSub(dep) });
}
private registerDeps = new Set<Stateful<any>>();
private addSub(dep: Stateful<any>) {
if (!this.registerDeps.has(dep)) {
// 订阅了一个更新,如果原子state发生变化,走一个this.updateSelector
dep.subscribe(() => this.updateSelector());
this.registerDeps.add(dep);
}
// 相当于Selector 通过Hooks强制让组件更新,更新之后触发
// Selector内部的更新
return dep.snapshot();
}
private updateSelector() {
this.update(
this.generate({
get: (dep) => this.addSub(dep),
})
);
}
}
// 生成类型用的 这个get哪里来的?
//
type SelectorGenerator<V> = (content: { get: <V>(dep: Stateful<V>) => V }) => V;
function selector<V>(value: { key: string; get: SelectorGenerator<V> }) {
return new Selector<V>(value.get);
}
function atom<T>(value: { key: string; default: T }) {
// 使用默认值创建Atom对象
return new Atom(value.default);
}
// useRecoilValue里利用useState和useEffect监听state变化
//
function useRecoilValue<T>(value: Stateful<T>) {
const [defState, updateState] = useState({});
useEffect(() => {
// {}不等于value, 强制执行useEffect更新
const { disconnect } = value.subscribe(() => updateState({}));
return () => {
disconnect();
};
}, [value]);
return value.snapshot();
}
function tuplify<T extends any[]>(...element: T) {
return element;
}
function useRecoilState<T>(atom: Atom<T>) {
const value = useRecoilValue(atom);
return tuplify(
value,
// 解决this找不到的问题,同时只要atom不变,set函数就不变
useCallback(
(val) => {
atom.setState(val);
},
[atom]
)
);
}
export { atom, useRecoilValue, useRecoilState };
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139