Skip to content

Commit 1771fce

Browse files
authored
fix: react18 submenu flicker (#551)
1 parent 2a2d956 commit 1771fce

File tree

1 file changed

+40
-35
lines changed

1 file changed

+40
-35
lines changed

src/Menu.tsx

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -247,23 +247,6 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
247247
);
248248
}
249249

250-
// ========================= Mode =========================
251-
const [mergedMode, mergedInlineCollapsed] = React.useMemo<
252-
[MenuMode, boolean]
253-
>(() => {
254-
if ((mode === 'inline' || mode === 'vertical') && inlineCollapsed) {
255-
return ['vertical', inlineCollapsed];
256-
}
257-
return [mode, false];
258-
}, [mode, inlineCollapsed]);
259-
260-
// ====================== Responsive ======================
261-
const [lastVisibleIndex, setLastVisibleIndex] = React.useState(0);
262-
const allVisible =
263-
lastVisibleIndex >= childList.length - 1 ||
264-
mergedMode !== 'horizontal' ||
265-
disabledOverflow;
266-
267250
// ========================= Open =========================
268251
const [mergedOpenKeys, setMergedOpenKeys] = useMergedState(defaultOpenKeys, {
269252
value: openKeys,
@@ -279,30 +262,52 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
279262
const [inlineCacheOpenKeys, setInlineCacheOpenKeys] =
280263
React.useState(mergedOpenKeys);
281264

282-
const isInlineMode = mergedMode === 'inline';
283-
284265
const mountRef = React.useRef(false);
285266

286-
// Cache
287-
React.useEffect(() => {
288-
if (isInlineMode) {
289-
setInlineCacheOpenKeys(mergedOpenKeys);
267+
// ========================= Mode =========================
268+
const [mergedMode, mergedInlineCollapsed] = React.useMemo<
269+
[MenuMode, boolean]
270+
>(() => {
271+
if ((mode === 'inline' || mode === 'vertical') && inlineCollapsed) {
272+
return ['vertical', inlineCollapsed];
290273
}
291-
}, [mergedOpenKeys]);
274+
return [mode, false];
275+
}, [mode, inlineCollapsed]);
276+
277+
const isInlineMode = mergedMode === 'inline';
278+
279+
const [internalMode, setInternalMode] = React.useState(mergedMode);
280+
const [internalInlineCollapsed, setInternalInlineCollapsed] = React.useState(mergedInlineCollapsed);
292281

293-
// Restore
294282
React.useEffect(() => {
283+
setInternalMode(mergedMode);
284+
setInternalInlineCollapsed(mergedInlineCollapsed)
285+
295286
if (!mountRef.current) {
296287
return;
297288
}
298-
289+
// Synchronously update MergedOpenKeys
299290
if (isInlineMode) {
300291
setMergedOpenKeys(inlineCacheOpenKeys);
301292
} else {
302293
// Trigger open event in case its in control
303294
triggerOpenKeys(EMPTY_LIST);
304295
}
305-
}, [isInlineMode]);
296+
}, [mergedMode, mergedInlineCollapsed]);
297+
298+
// ====================== Responsive ======================
299+
const [lastVisibleIndex, setLastVisibleIndex] = React.useState(0);
300+
const allVisible =
301+
lastVisibleIndex >= childList.length - 1 ||
302+
internalMode !== 'horizontal' ||
303+
disabledOverflow;
304+
305+
// Cache
306+
React.useEffect(() => {
307+
if (isInlineMode) {
308+
setInlineCacheOpenKeys(mergedOpenKeys);
309+
}
310+
}, [mergedOpenKeys]);
306311

307312
React.useEffect(() => {
308313
mountRef.current = true;
@@ -431,7 +436,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
431436
}
432437

433438
// Whatever selectable, always close it
434-
if (!multiple && mergedOpenKeys.length && mergedMode !== 'inline') {
439+
if (!multiple && mergedOpenKeys.length && internalMode !== 'inline') {
435440
triggerOpenKeys(EMPTY_LIST);
436441
}
437442
};
@@ -450,7 +455,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
450455

451456
if (open) {
452457
newOpenKeys.push(key);
453-
} else if (mergedMode !== 'inline') {
458+
} else if (internalMode !== 'inline') {
454459
// We need find all related popup to close
455460
const subPathKeys = getSubPathKeys(key);
456461
newOpenKeys = newOpenKeys.filter(k => !subPathKeys.has(k));
@@ -471,7 +476,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
471476
};
472477

473478
const onInternalKeyDown = useAccessibility(
474-
mergedMode,
479+
internalMode,
475480
mergedActiveKey,
476481
isRtl,
477482
uuid,
@@ -504,7 +509,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
504509

505510
// >>>>> Children
506511
const wrappedChildList =
507-
mergedMode !== 'horizontal' || disabledOverflow
512+
internalMode !== 'horizontal' || disabledOverflow
508513
? childList
509514
: // Need wrap for overflow dropdown that do not response for open
510515
childList.map((child, index) => (
@@ -528,10 +533,10 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
528533
className={classNames(
529534
prefixCls,
530535
`${prefixCls}-root`,
531-
`${prefixCls}-${mergedMode}`,
536+
`${prefixCls}-${internalMode}`,
532537
className,
533538
{
534-
[`${prefixCls}-inline-collapsed`]: mergedInlineCollapsed,
539+
[`${prefixCls}-inline-collapsed`]: internalInlineCollapsed,
535540
[`${prefixCls}-rtl`]: isRtl,
536541
},
537542
rootClassName,
@@ -561,7 +566,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
561566
);
562567
}}
563568
maxCount={
564-
mergedMode !== 'horizontal' || disabledOverflow
569+
internalMode !== 'horizontal' || disabledOverflow
565570
? Overflow.INVALIDATE
566571
: Overflow.RESPONSIVE
567572
}
@@ -582,7 +587,7 @@ const Menu = React.forwardRef<MenuRef, MenuProps>((props, ref) => {
582587
<MenuContextProvider
583588
prefixCls={prefixCls}
584589
rootClassName={rootClassName}
585-
mode={mergedMode}
590+
mode={internalMode}
586591
openKeys={mergedOpenKeys}
587592
rtl={isRtl}
588593
// Disabled

0 commit comments

Comments
 (0)