From 7fd7bc542a3f6bb4c7e7a753178a09e2d3184b2d Mon Sep 17 00:00:00 2001 From: janrywang Date: Mon, 11 Oct 2021 10:31:48 +0800 Subject: [PATCH] fix(reactive): fix reaction force untrack will effect to setState --- .../reactive/src/__tests__/autorun.spec.ts | 22 ++++++++ packages/reactive/src/autorun.ts | 50 +++++++------------ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/packages/reactive/src/__tests__/autorun.spec.ts b/packages/reactive/src/__tests__/autorun.spec.ts index f6ba8fb8bfc..e5576adb4e8 100644 --- a/packages/reactive/src/__tests__/autorun.spec.ts +++ b/packages/reactive/src/__tests__/autorun.spec.ts @@ -68,6 +68,28 @@ test('reaction fireImmediately', () => { expect(handler).toBeCalledTimes(2) }) +test('reaction untrack handler', () => { + const obs = observable({ + aa: { + bb: 123, + cc: 123, + }, + }) + const handler = jest.fn() + const dispose = reaction( + () => { + return obs.aa.bb + }, + () => { + handler(obs.aa.cc) + } + ) + obs.aa.bb = 222 + obs.aa.cc = 222 + expect(handler).toBeCalledTimes(1) + dispose() +}) + test('reaction dirty check', () => { const obs: any = { aa: 123, diff --git a/packages/reactive/src/autorun.ts b/packages/reactive/src/autorun.ts index fff80ce1fc7..f960732d378 100644 --- a/packages/reactive/src/autorun.ts +++ b/packages/reactive/src/autorun.ts @@ -1,8 +1,6 @@ import { batchEnd, batchStart, - untrackEnd, - untrackStart, disposeBindingReactions, releaseBindingReactions, disposeEffects, @@ -18,14 +16,6 @@ interface IValue { oldValue?: any } -interface IInitialized { - current?: boolean -} - -interface IDirty { - current?: boolean -} - export const autorun = (tracker: Reaction, name = 'AutoRun') => { const reaction: Reaction = () => { if (!isFn(tracker)) return @@ -119,47 +109,43 @@ export const reaction = ( ...options, } const value: IValue = {} - const initialized: IInitialized = {} - const dirty: IDirty = {} const dirtyCheck = () => { if (isFn(realOptions.equals)) return !realOptions.equals(value.oldValue, value.currentValue) return value.oldValue !== value.currentValue } - const reaction = () => { + const fireAction = () => { + try { + batchStart() + if (isFn(subscriber)) subscriber(value.currentValue, value.oldValue) + } finally { + batchEnd() + } + } + + const reaction: Reaction = () => { if (ReactionStack.indexOf(reaction) === -1) { releaseBindingReactions(reaction) try { ReactionStack.push(reaction) value.currentValue = tracker() - dirty.current = dirtyCheck() } finally { ReactionStack.pop() } } - - if ( - (dirty.current && initialized.current) || - (!initialized.current && realOptions.fireImmediately) - ) { - try { - batchStart() - untrackStart() - if (isFn(subscriber)) subscriber(value.currentValue, value.oldValue) - } finally { - untrackEnd() - batchEnd() - } - } - + } + reaction._scheduler = (looping) => { + looping() + if (dirtyCheck()) fireAction() value.oldValue = value.currentValue - initialized.current = true } - reaction._name = realOptions.name reaction() - + value.oldValue = value.currentValue + if (realOptions.fireImmediately) { + fireAction() + } return () => { disposeBindingReactions(reaction) }