fix: when the setting-field value is array, the observer invalid

This commit is contained in:
liujuping 2023-03-31 10:58:55 +08:00 committed by 林熠
parent d64da1e065
commit 4bb4296229
3 changed files with 75 additions and 3 deletions

View File

@ -162,12 +162,21 @@ export class Prop implements IProp, IPropParent {
return runInAction(() => {
let items: IProp[] | null = null;
if (this._type === 'list') {
const maps = new Map<string, IProp>();
const data = this._value;
data.forEach((item: any, idx: number) => {
items = items || [];
items.push(new Prop(this, item, idx));
let prop;
if (this._prevMaps?.has(idx.toString())) {
prop = this._prevMaps.get(idx.toString())!;
prop.setValue(item);
} else {
prop = new Prop(this, item, idx);
}
maps.set(idx.toString(), prop);
items.push(prop);
});
this._maps = null;
this._maps = maps;
} else if (this._type === 'map') {
const data = this._value;
const maps = new Map<string, IProp>();
@ -377,6 +386,8 @@ export class Prop implements IProp, IPropParent {
}
this.dispose();
// setValue 的时候,如果不重新建立 itemsitems 的 setValue 没有触发,会导致子项的响应式逻辑不能被触发
this.setupItems();
if (oldValue !== this._value) {
const propsInfo = {

View File

@ -182,5 +182,66 @@ describe('setting-field 测试', () => {
expect(mockFn).toHaveBeenCalled();
});
it('autorun', async () => {
const settingEntry = mockNode.settingEntry as SettingTopEntry;
const arrField = settingEntry.get('columns');
const subArrField = arrField.createField({
name: 0,
title: 'sub',
});
const objSubField = subArrField.createField({
name: 'objSub',
title: 'objSub',
});
const mockFnArrField = jest.fn();
const mockFnSubArrField = jest.fn();
const mockFnObjSubField = jest.fn();
arrField.setValue([{ objSub: "subMock0.Index.0" }]);
// 这里需要 setValue 两遍,触发 prop 的 purge 方法,使 purged 为 true之后的 purge 方法不会正常执行prop 才能正常缓存autorun 才能正常执行
// TODO: 该机制后续得研究一下,再确定是否要修改
arrField.setValue([{ objSub: "subMock0.Index.0" }]);
arrField.onEffect(() => {
mockFnArrField(arrField.getValue());
});
arrField.onEffect(() => {
mockFnSubArrField(subArrField.getValue());
});
arrField.onEffect(() => {
mockFnObjSubField(objSubField.getValue());
});
await delayObxTick();
expect(mockFnObjSubField).toHaveBeenCalledWith('subMock0.Index.0');
expect(mockFnSubArrField).toHaveBeenCalledWith({ objSub: "subMock0.Index.0" });
expect(mockFnArrField).toHaveBeenCalledWith([{ objSub: "subMock0.Index.0" }]);
arrField.setValue([{ objSub: "subMock0.Index.1" }]);
await delayObxTick();
expect(mockFnObjSubField).toHaveBeenCalledWith('subMock0.Index.1');
expect(mockFnSubArrField).toHaveBeenCalledWith({ objSub: "subMock0.Index.1" });
expect(mockFnArrField).toHaveBeenCalledWith([{ objSub: "subMock0.Index.1" }]);
subArrField.setValue({ objSub: "subMock0.Index.2" });
await delayObxTick();
expect(mockFnObjSubField).toHaveBeenCalledWith('subMock0.Index.2');
expect(mockFnSubArrField).toHaveBeenCalledWith({ objSub: "subMock0.Index.2" });
expect(mockFnArrField).toHaveBeenCalledWith([{ objSub: "subMock0.Index.2" }]);
objSubField.setValue('subMock0.Index.3');
await delayObxTick();
expect(mockFnObjSubField).toHaveBeenCalledWith('subMock0.Index.3');
expect(mockFnSubArrField).toHaveBeenCalledWith({ objSub: "subMock0.Index.3" });
expect(mockFnArrField).toHaveBeenCalledWith([{ objSub: "subMock0.Index.3" }]);
})
});
});

View File

@ -22,7 +22,7 @@ window.console.warn = () => {};
const originalLog = window.console.log;
window.console.log = (...args) => {
// suppress boring warnings
if (args[0].includes('@babel/plugin-proposal-private-property-in-object')) return;
if (args[0]?.includes && args[0].includes('@babel/plugin-proposal-private-property-in-object')) return;
originalLog.apply(window.console, args);
};
window.React = window.React || {};