Skip to content

Commit

Permalink
fix: deepclone items when getOverflowItem to Prevent props.items from…
Browse files Browse the repository at this point in the history
… being changed internally due to rapid clicks (#2423)

* fix: deepclone items when getOverflowItem to Prevent props.items from being changed internally due to rapid clicks
* fix: change clonedeep to fast-copy copy
  • Loading branch information
YannLynn authored Aug 19, 2024
1 parent 896e1b8 commit cf816b2
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
10 changes: 6 additions & 4 deletions packages/semi-foundation/overflowList/foundation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BaseFoundation, { DefaultAdapter } from '../base/foundation';
import { strings } from './constants';
import { noop, get } from 'lodash';
import { get, cloneDeep } from 'lodash';
import copy from 'fast-copy';

const Boundary = strings.BOUNDARY_MAP;
Expand Down Expand Up @@ -33,13 +33,15 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
return overflow;
}

const visibleStateArr = items.map(({ key }: { key: string }) => Boolean(visibleState.get(key)));
const cloneItems = copy(items);

const visibleStateArr = cloneItems.map(({ key }: { key: string }) => Boolean(visibleState.get(key)));
const visibleStart = visibleStateArr.indexOf(true);
const visibleEnd = visibleStateArr.lastIndexOf(true);

const overflowList = [];
overflowList[0] = visibleStart >= 0 ? items.slice(0, visibleStart) : [];
overflowList[1] = visibleEnd >= 0 ? items.slice(visibleEnd + 1, items.length) : items;
overflowList[0] = visibleStart >= 0 ? cloneItems.slice(0, visibleStart) : [];
overflowList[1] = visibleEnd >= 0 ? cloneItems.slice(visibleEnd + 1, cloneItems.length) : cloneItems;
return overflowList;
}

Expand Down
15 changes: 8 additions & 7 deletions packages/semi-ui/overflowList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import IntersectionObserver from './intersectionObserver';
import OverflowListFoundation, { OverflowListAdapter } from '@douyinfe/semi-foundation/overflowList/foundation';

import '@douyinfe/semi-foundation/overflowList/overflowList.scss';
import { cloneDeep, getDefaultPropsFromGlobalConfig } from '../_utils';
import { getDefaultPropsFromGlobalConfig } from '../_utils';
import copy from 'fast-copy';

const prefixCls = cssClasses.PREFIX;
const Boundary = strings.BOUNDARY_MAP;
Expand All @@ -20,7 +21,7 @@ const RenderMode = strings.MODE_MAP;
export type { ReactIntersectionObserverProps } from './intersectionObserver';
export type OverflowItem = Record<string, any>;

type Key = string|number
type Key = string | number

export interface OverflowListProps {
className?: string;
Expand All @@ -38,7 +39,7 @@ export interface OverflowListProps {
wrapperStyle?: CSSProperties;
itemKey?: Key | ((item: OverflowItem) => Key);
onVisibleStateChange?: (visibleState: Map<string, boolean>) => void;
overflowRenderDirection?: "both"|"start"|'end' // used in tabs, not exposed to user
overflowRenderDirection?: "both" | "start" | 'end' // used in tabs, not exposed to user
}

export interface OverflowListState {
Expand Down Expand Up @@ -134,8 +135,8 @@ class OverflowList extends BaseComponent<OverflowListProps, OverflowListState> {
}

const isCollapseFromStart = props.collapseFrom === Boundary.START;
const visible = isCollapseFromStart ? cloneDeep(props.items).reverse().slice(0, maxCount) : props.items.slice(0, maxCount);
const overflow = isCollapseFromStart ? cloneDeep(props.items).reverse().slice(maxCount) : props.items.slice(maxCount);
const visible = isCollapseFromStart ? copy(props.items).reverse().slice(0, maxCount) : props.items.slice(0, maxCount);
const overflow = isCollapseFromStart ? copy(props.items).reverse().slice(maxCount) : props.items.slice(maxCount);
newState.visible = visible;
newState.overflow = overflow;
newState.maxCount = maxCount;
Expand All @@ -150,7 +151,7 @@ class OverflowList extends BaseComponent<OverflowListProps, OverflowListState> {
return {
...super.adapter,
updateVisibleState: (visibleState): void => {
this.setState({ visibleState }, ()=>{
this.setState({ visibleState }, () => {
this.props.onVisibleStateChange?.(visibleState);
});
},
Expand Down Expand Up @@ -266,7 +267,7 @@ class OverflowList extends BaseComponent<OverflowListProps, OverflowListState> {
}
const inner =
renderMode === RenderMode.SCROLL ?
(()=>{
(() => {
const list = [<div
className={cls(wrapperClassName, `${prefixCls}-scroll-wrapper`)}
ref={(ref): void => {
Expand Down
12 changes: 12 additions & 0 deletions packages/semi-ui/tabs/_story/tabs.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1058,4 +1058,16 @@ export const ShowRestInDropdownDemo = () => {
))}
</Tabs>
)
}

export const Fix2415 = () => {
return (
<Tabs style={{ width: 250, margin: '20px' }} type="card" collapsible>
{[10,2324325324324,1111].map(i => (
<TabPane tab={`Tab-${i}`} itemKey={`Tab-${i}`} key={i}>
Content of card tab {i}.Quickly click the right arrow and observe that the arrow is disabled correctly.
</TabPane>
))}
</Tabs>
)
}

0 comments on commit cf816b2

Please sign in to comment.