diff --git a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts index 8e029fb6..9334116f 100644 --- a/libs/horizon/src/renderer/diff/nodeDiffComparator.ts +++ b/libs/horizon/src/renderer/diff/nodeDiffComparator.ts @@ -294,8 +294,9 @@ function diffArrayNodesHandler( if (rightOldIndex < 0 || rightOldNode === null) { break; } - - canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1]); + // 新旧节点的index应该相同才能复用,null会影响位置 + const samePosition = rightOldNode.eIndex === rightIdx - 1; + canBeReuse = checkCanReuseNode(rightOldNode, newChildren[rightIdx - 1]) && samePosition; // 不能复用,break if (!canBeReuse) { break; diff --git a/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js b/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js new file mode 100644 index 00000000..0f5ab14d --- /dev/null +++ b/scripts/__tests__/ComponentTest/DiffAlgorithm.test.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + */ + +import * as Horizon from '@cloudsop/horizon/index.ts'; + +describe('Diff Algorithm', () => { + it('null should diff correctly', () => { + const fn = jest.fn(); + + class C extends Horizon.Component { + constructor() { + super(); + fn(); + } + + render() { + return 1; + } + } + + let update; + + function App() { + const [current, setCurrent] = Horizon.useState(1); + update = setCurrent; + return ( + <> + {current === 1 ? : null} + {current === 2 ? : null} + {current === 3 ? : null} + + ); + } + + Horizon.render(, container); + expect(fn).toHaveBeenCalledTimes(1); + + update(2); + expect(fn).toHaveBeenCalledTimes(2); + + update(3); + expect(fn).toHaveBeenCalledTimes(3); + + update(1); + expect(fn).toHaveBeenCalledTimes(4); + }); +}); diff --git a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js index a88cb813..443894a5 100644 --- a/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js +++ b/scripts/__tests__/ComponentTest/HookTest/UseEffect.test.js @@ -81,7 +81,7 @@ describe('useEffect Hook Test', () => { expect(LogUtils.getAndClear()).toEqual([]); // 在执行新的render前,会执行完上一次render的useEffect,所以LogUtils会加入'NewApp effect'。 Horizon.render([na], container); - expect(LogUtils.getAndClear()).toEqual(['NewApp effect']); + expect(LogUtils.getAndClear()).toEqual(['NewApp effect', 'NewApp']); expect(container.textContent).toBe('NewApp'); expect(LogUtils.getAndClear()).toEqual([]); });