diff --git a/packages/inula/scripts/__tests__/ComponentTest/StrictMode.test.js b/packages/inula/scripts/__tests__/ComponentTest/StrictMode.test.js
new file mode 100644
index 00000000..a12fbed4
--- /dev/null
+++ b/packages/inula/scripts/__tests__/ComponentTest/StrictMode.test.js
@@ -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 (
+
+
+
+
+ );
+ };
+
+ const Child = () => {
+ const isMount = useRef(false);
+
+ useEffect(() => {
+ if (!isMount.current) {
+ LogUtils.log('didMount');
+ isMount.current = true;
+ } else {
+ LogUtils.log('didUpdate');
+ }
+ });
+
+ return null;
+ };
+
+ act(() => render(, container));
+ // 子组件初始化,会挂载一次
+ expect(LogUtils.getAndClear()).toStrictEqual(['didMount']);
+ const button = container.querySelector('#btn');
+ // 父组件State更新,子组件也会更新一次
+ act(() => button.click());
+ expect(LogUtils.getAndClear()).toStrictEqual(['didUpdate']);
+ });
+});
diff --git a/packages/inula/src/renderer/diff/nodeDiffComparator.ts b/packages/inula/src/renderer/diff/nodeDiffComparator.ts
index bb07e3ef..e7161174 100644
--- a/packages/inula/src/renderer/diff/nodeDiffComparator.ts
+++ b/packages/inula/src/renderer/diff/nodeDiffComparator.ts
@@ -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标记为删除