Skip to content

vue-next effect function will be called more than once when Array.prototype.shift be called #10705

Closed
@HowGraceU

Description

@HowGraceU

Version

vue-next

Reproduction link

HowGraceU/vue-next@de01ffb#diff-d1223243b498cec786e7864834bc0acfL158

Steps to reproduce

  it('should observe iteration', () => {
    let dummy
    const list = reactive(['Hello'])
    const fn = jest.fn(() => (dummy = list.join(' ')));
    effect(fn)

    expect(fn).toHaveBeenCalledTimes(1) // normal

    expect(dummy).toBe('Hello')
    list.push('World!')
    expect(dummy).toBe('Hello World!')

    expect(fn).toHaveBeenCalledTimes(2) // normal

    list.shift()
    expect(dummy).toBe('World!')

    expect(fn).toHaveBeenCalledTimes(5) // It depends on list.length
  })

What is expected?

effect should only be called once

What is actually happening?

effect is called more than once


this is due to shift will trigger set function more than once

a = new Proxy([1,2,3,4,5,6,7,8,9,10], {
	set(target, key, value, p) {
		const oldValue = target[key];
		console.log(`key:${key} oldValue: ${oldValue}  v:${value}`);
		return Reflect.set(target, key, value, p);
	}
	
});

a.shift();

/*
* log 
* key:0 oldValue: 1  v:2
* key:1 oldValue: 2  v:3
* key:2 oldValue: 3  v:4
* key:3 oldValue: 4  v:5
* key:4 oldValue: 5  v:6
* key:5 oldValue: 6  v:7
* key:6 oldValue: 7  v:8
* key:7 oldValue: 8  v:9
* key:8 oldValue: 9  v:10
* key:length oldValue: 10  v:9
*/

should cache effect funtion, like Watch Object in Vue 2, and trigger it nexttick?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions