修复StrictMode组件导致子组件状态丢失的问题
This commit is contained in:
parent
5b0ed0a5aa
commit
0022a6b55a
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Huawei Technologies Co.,Ltd.
|
||||
*
|
||||
* openInula is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
*
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
import * as Inula from '../../../src/index';
|
||||
import { getLogUtils } from '../jest/testUtils';
|
||||
|
||||
describe('StrictMode Component test', () => {
|
||||
const LogUtils = getLogUtils();
|
||||
const { useState, useEffect, useRef, render, act } = Inula;
|
||||
it('StrictMode is same to Fragment', () => {
|
||||
const Parent = () => {
|
||||
const [, setS] = useState('1');
|
||||
return (
|
||||
<Inula.StrictMode>
|
||||
<button id="btn" onClick={() => setS(prevState => prevState + '!')}>
|
||||
Click
|
||||
</button>
|
||||
<Child />
|
||||
</Inula.StrictMode>
|
||||
);
|
||||
};
|
||||
|
||||
const Child = () => {
|
||||
const isMount = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isMount.current) {
|
||||
LogUtils.log('didMount');
|
||||
isMount.current = true;
|
||||
} else {
|
||||
LogUtils.log('didUpdate');
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
act(() => render(<Parent />, container));
|
||||
// 子组件初始化,会挂载一次
|
||||
expect(LogUtils.getAndClear()).toStrictEqual(['didMount']);
|
||||
const button = container.querySelector('#btn');
|
||||
// 父组件State更新,子组件也会更新一次
|
||||
act(() => button.click());
|
||||
expect(LogUtils.getAndClear()).toStrictEqual(['didUpdate']);
|
||||
});
|
||||
});
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
import type { VNode } from '../Types';
|
||||
import { FlagUtils } from '../vnode/VNodeFlags';
|
||||
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL } from '../../external/JSXElementType';
|
||||
import { TYPE_COMMON_ELEMENT, TYPE_FRAGMENT, TYPE_PORTAL, TYPE_STRICT_MODE } from '../../external/JSXElementType';
|
||||
import { DomText, DomPortal, Fragment, DomComponent } from '../vnode/VNodeTags';
|
||||
import {
|
||||
updateVNode,
|
||||
|
@ -35,9 +35,9 @@ enum DiffCategory {
|
|||
ARR_NODE = 'ARR_NODE',
|
||||
}
|
||||
|
||||
// 检查是不是被 FRAGMENT 包裹
|
||||
function isNoKeyFragment(child: any) {
|
||||
return child != null && child.type === TYPE_FRAGMENT && child.key === null;
|
||||
// 检查是不是被 FRAGMENT 或 StrictMode 包裹
|
||||
function isNoKeyFragmentOrStrictMode(child: any) {
|
||||
return child != null && (child.type === TYPE_FRAGMENT || child.type === TYPE_STRICT_MODE) && child.key === null;
|
||||
}
|
||||
|
||||
// 清除单个节点
|
||||
|
@ -631,7 +631,7 @@ export function createChildrenByDiff(
|
|||
newChild: any,
|
||||
isComparing: boolean
|
||||
): VNode | null {
|
||||
const isFragment = isNoKeyFragment(newChild);
|
||||
const isFragment = isNoKeyFragmentOrStrictMode(newChild);
|
||||
newChild = isFragment ? newChild.props.children : newChild;
|
||||
|
||||
// 1. 没有新节点,直接把vNode标记为删除
|
||||
|
|
Loading…
Reference in New Issue