Skip to content

Commit a8686bb

Browse files
authored
feat: add customRef (#423)
1 parent 1ceac1d commit a8686bb

File tree

4 files changed

+56
-30
lines changed

4 files changed

+56
-30
lines changed

src/apis/state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export {
55
markReactive,
66
reactive,
77
ref,
8+
customRef,
89
Ref,
910
set,
1011
shallowReactive,

src/reactivity/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export {
99
} from './reactive'
1010
export {
1111
ref,
12+
customRef,
1213
isRef,
1314
Ref,
1415
createRef,

src/reactivity/ref.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,26 @@ export function toRefs<T extends Data = Data>(obj: T): ToRefs<T> {
128128
return ret
129129
}
130130

131+
export type CustomRefFactory<T> = (
132+
track: () => void,
133+
trigger: () => void
134+
) => {
135+
get: () => T
136+
set: (value: T) => void
137+
}
138+
139+
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
140+
const version = ref(0)
141+
return createRef(
142+
factory(
143+
() => void version.value,
144+
() => {
145+
++version.value
146+
}
147+
)
148+
)
149+
}
150+
131151
export function toRef<T extends object, K extends keyof T>(
132152
object: T,
133153
key: K

test/v3/reactivity/ref.spec.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
ref,
3+
customRef,
34
reactive,
45
isRef,
56
toRef,
@@ -308,34 +309,37 @@ describe('reactivity/ref', () => {
308309
expect(dummyY).toBe(5)
309310
})
310311

311-
// test('customRef', () => {
312-
// let value = 1;
313-
// let _trigger: () => void;
314-
315-
// const custom = customRef((track, trigger) => ({
316-
// get() {
317-
// track();
318-
// return value;
319-
// },
320-
// set(newValue: number) {
321-
// value = newValue;
322-
// _trigger = trigger;
323-
// },
324-
// }));
325-
326-
// expect(isRef(custom)).toBe(true);
327-
328-
// let dummy;
329-
// watchEffect(() => {
330-
// dummy = custom.value;
331-
// }, {flush: 'sync'});
332-
// expect(dummy).toBe(1);
333-
334-
// custom.value = 2;
335-
// // should not trigger yet
336-
// expect(dummy).toBe(1);
337-
338-
// _trigger!();
339-
// expect(dummy).toBe(2);
340-
// });
312+
test('customRef', () => {
313+
let value = 1
314+
let _trigger: () => void
315+
316+
const custom = customRef((track, trigger) => ({
317+
get() {
318+
track()
319+
return value
320+
},
321+
set(newValue: number) {
322+
value = newValue
323+
_trigger = trigger
324+
},
325+
}))
326+
327+
expect(isRef(custom)).toBe(true)
328+
329+
let dummy
330+
watchEffect(
331+
() => {
332+
dummy = custom.value
333+
},
334+
{ flush: 'sync' }
335+
)
336+
expect(dummy).toBe(1)
337+
338+
custom.value = 2
339+
// should not trigger yet
340+
expect(dummy).toBe(1)
341+
342+
_trigger!()
343+
expect(dummy).toBe(2)
344+
})
341345
})

0 commit comments

Comments
 (0)