expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
})
+ it('should chained computeds keep reactivity when computed effect happens', async () => {
+ const v = ref('Hello')
+ const c = computed(() => {
+ v.value += ' World'
+ return v.value
+ })
+ const d = computed(() => c.value)
+ const e = computed(() => d.value)
+ const Comp = {
+ setup: () => {
+ return () => d.value + ' | ' + e.value
+ },
+ }
+ const root = nodeOps.createElement('div')
+
+ render(h(Comp), root)
+ await nextTick()
+ expect(serializeInner(root)).toBe('Hello World | Hello World')
+
+ v.value += ' World'
+ await nextTick()
+ expect(serializeInner(root)).toBe(
+ 'Hello World World World | Hello World World World',
+ )
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
+ })
+
+ it('should keep dirty level when side effect computed value changed', () => {
+ const v = ref(0)
+ const c = computed(() => {
+ v.value += 1
+ return v.value
+ })
+ const d = computed(() => {
+ return { d: c.value }
+ })
+
+ const Comp = {
+ setup: () => {
+ return () => {
+ return [d.value.d, d.value.d]
+ }
+ },
+ }
+
+ const root = nodeOps.createElement('div')
+ render(h(Comp), root)
+
+ expect(d.value.d).toBe(1)
+ expect(serializeInner(root)).toBe('11')
+ expect(c.effect._dirtyLevel).toBe(
+ DirtyLevels.MaybeDirty_ComputedSideEffect_Origin,
+ )
+ expect(d.effect._dirtyLevel).toBe(DirtyLevels.MaybeDirty_ComputedSideEffect)
+ expect(COMPUTED_SIDE_EFFECT_WARN).toHaveBeenWarned()
+ })
+
it('debug: onTrigger (ref)', () => {
let events: DebuggerEvent[] = []
const onTrigger = vi.fn((e: DebuggerEvent) => {
get value() {
// the computed ref may get wrapped by other proxies e.g. readonly() #3376
const self = toRaw(this)
+ const lastDirtyLevel = self.effect._dirtyLevel
if (
(!self._cacheable || self.effect.dirty) &&
hasChanged(self._value, (self._value = self.effect.run()!))
) {
- triggerRefValue(self, DirtyLevels.Dirty)
+ // keep dirty level when side effect computed's value changed
+ if (lastDirtyLevel !== DirtyLevels.MaybeDirty_ComputedSideEffect) {
+ triggerRefValue(self, DirtyLevels.Dirty)
+ }
}
trackRefValue(self)
if (