Skip to content

Commit

Permalink
fix(reactive): fix reaction force untrack will effect to setState (#2278
Browse files Browse the repository at this point in the history
)
  • Loading branch information
janryWang committed Oct 11, 2021
1 parent 200253e commit 17b9315
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 32 deletions.
22 changes: 22 additions & 0 deletions packages/reactive/src/__tests__/autorun.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
50 changes: 18 additions & 32 deletions packages/reactive/src/autorun.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
batchEnd,
batchStart,
untrackEnd,
untrackStart,
disposeBindingReactions,
releaseBindingReactions,
disposeEffects,
Expand All @@ -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
Expand Down Expand Up @@ -119,47 +109,43 @@ export const reaction = <T>(
...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)
}
Expand Down

0 comments on commit 17b9315

Please sign in to comment.