fix(reactivity): ensure computed always expose value
fix #3099 Also changes the original fix for #910 by moving the fix from reactivity to the scheduler
This commit is contained in:
@@ -193,4 +193,10 @@ describe('reactivity/computed', () => {
|
||||
expect(isReadonly(z)).toBe(false)
|
||||
expect(isReadonly(z.value.a)).toBe(false)
|
||||
})
|
||||
|
||||
it('should expose value when stopped', () => {
|
||||
const x = computed(() => 1)
|
||||
stop(x.effect)
|
||||
expect(x.value).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -709,28 +709,6 @@ describe('reactivity/effect', () => {
|
||||
expect(dummy).toBe(3)
|
||||
})
|
||||
|
||||
it('stop with scheduler', () => {
|
||||
let dummy
|
||||
const obj = reactive({ prop: 1 })
|
||||
const queue: (() => void)[] = []
|
||||
const runner = effect(
|
||||
() => {
|
||||
dummy = obj.prop
|
||||
},
|
||||
{
|
||||
scheduler: e => queue.push(e)
|
||||
}
|
||||
)
|
||||
obj.prop = 2
|
||||
expect(dummy).toBe(1)
|
||||
expect(queue.length).toBe(1)
|
||||
stop(runner)
|
||||
|
||||
// a scheduled effect should not execute anymore after stopped
|
||||
queue.forEach(e => e())
|
||||
expect(dummy).toBe(1)
|
||||
})
|
||||
|
||||
it('events: onStop', () => {
|
||||
const onStop = jest.fn()
|
||||
const runner = effect(() => {}, {
|
||||
|
||||
@@ -26,6 +26,21 @@ export interface ReactiveEffectOptions {
|
||||
onTrack?: (event: DebuggerEvent) => void
|
||||
onTrigger?: (event: DebuggerEvent) => void
|
||||
onStop?: () => void
|
||||
/**
|
||||
* Indicates whether the job is allowed to recursively trigger itself when
|
||||
* managed by the scheduler.
|
||||
*
|
||||
* By default, a job cannot trigger itself because some built-in method calls,
|
||||
* e.g. Array.prototype.push actually performs reads as well (#1740) which
|
||||
* can lead to confusing infinite loops.
|
||||
* The allowed cases are component update functions and watch callbacks.
|
||||
* Component update functions may update child component props, which in turn
|
||||
* trigger flush: "pre" watch callbacks that mutates state that the parent
|
||||
* relies on (#1801). Watch callbacks doesn't track its dependencies so if it
|
||||
* triggers itself again, it's likely intentional and it is the user's
|
||||
* responsibility to perform recursive state mutation that eventually
|
||||
* stabilizes (#1727).
|
||||
*/
|
||||
allowRecurse?: boolean
|
||||
}
|
||||
|
||||
@@ -84,7 +99,7 @@ function createReactiveEffect<T = any>(
|
||||
): ReactiveEffect<T> {
|
||||
const effect = function reactiveEffect(): unknown {
|
||||
if (!effect.active) {
|
||||
return options.scheduler ? undefined : fn()
|
||||
return fn()
|
||||
}
|
||||
if (!effectStack.includes(effect)) {
|
||||
cleanup(effect)
|
||||
|
||||
Reference in New Issue
Block a user