Skip to content

Commit

Permalink
feat: add customRef (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
shaonialife committed Jul 5, 2020
1 parent 1ceac1d commit a8686bb
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/apis/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
markReactive,
reactive,
ref,
customRef,
Ref,
set,
shallowReactive,
Expand Down
1 change: 1 addition & 0 deletions src/reactivity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
} from './reactive'
export {
ref,
customRef,
isRef,
Ref,
createRef,
Expand Down
20 changes: 20 additions & 0 deletions src/reactivity/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ export function toRefs<T extends Data = Data>(obj: T): ToRefs<T> {
return ret
}

export type CustomRefFactory<T> = (
track: () => void,
trigger: () => void
) => {
get: () => T
set: (value: T) => void
}

export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
const version = ref(0)
return createRef(
factory(
() => void version.value,
() => {
++version.value
}
)
)
}

export function toRef<T extends object, K extends keyof T>(
object: T,
key: K
Expand Down
64 changes: 34 additions & 30 deletions test/v3/reactivity/ref.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
ref,
customRef,
reactive,
isRef,
toRef,
Expand Down Expand Up @@ -308,34 +309,37 @@ describe('reactivity/ref', () => {
expect(dummyY).toBe(5)
})

// test('customRef', () => {
// let value = 1;
// let _trigger: () => void;

// const custom = customRef((track, trigger) => ({
// get() {
// track();
// return value;
// },
// set(newValue: number) {
// value = newValue;
// _trigger = trigger;
// },
// }));

// expect(isRef(custom)).toBe(true);

// let dummy;
// watchEffect(() => {
// dummy = custom.value;
// }, {flush: 'sync'});
// expect(dummy).toBe(1);

// custom.value = 2;
// // should not trigger yet
// expect(dummy).toBe(1);

// _trigger!();
// expect(dummy).toBe(2);
// });
test('customRef', () => {
let value = 1
let _trigger: () => void

const custom = customRef((track, trigger) => ({
get() {
track()
return value
},
set(newValue: number) {
value = newValue
_trigger = trigger
},
}))

expect(isRef(custom)).toBe(true)

let dummy
watchEffect(
() => {
dummy = custom.value
},
{ flush: 'sync' }
)
expect(dummy).toBe(1)

custom.value = 2
// should not trigger yet
expect(dummy).toBe(1)

_trigger!()
expect(dummy).toBe(2)
})
})

0 comments on commit a8686bb

Please sign in to comment.