Skip to content
This repository was archived by the owner on Apr 11, 2025. It is now read-only.

Commit a3b31f5

Browse files
authored
🐛 fix: 重构并修复 setData 值时会出现的重复渲染卡死的问题
2 parents 13bdaeb + 2e812bc commit a3b31f5

31 files changed

+681
-385
lines changed

packages/sortable-list/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@
2727
"@dnd-kit/core": "^5.0.1",
2828
"@dnd-kit/modifiers": "^5.0.0",
2929
"@dnd-kit/sortable": "^6.0.0",
30+
"antd": "^4.18.9",
3031
"classnames": "^2.3.1",
3132
"lodash.isequal": "^4.5.0",
32-
"use-merge-value": "^1.0.2"
33+
"zustand": "^3.7.1"
3334
}
3435
}

packages/sortable-list/src/components/Action/index.less

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
@focused-outline-color: #4c9ffe;
2-
31
.Action {
42
display: flex;
53
width: 12px;
@@ -41,10 +39,4 @@
4139
fill: var(--fill, #788491);
4240
}
4341
}
44-
45-
&:focus-visible {
46-
outline: none;
47-
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0),
48-
0 0px 0px 2px @focused-outline-color;
49-
}
5042
}

packages/sortable-list/src/BaseItem/index.less renamed to packages/sortable-list/src/components/BaseItem/index.less

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
@background-color: #fff;
2-
@border-color: #efefef;
3-
@handle-color: rgba(0, 0, 0, 0.25);
1+
@import (reference) '~antd/es/style/themes/default.less';
2+
43
@box-shadow-border: 0 0 0 calc(1px / var(--scale-x, 1)) hsla(240, 0%, 26%, 0.05);
54
@box-shadow-common: 0 1px calc(3px / var(--scale-x, 1)) hsla(240, 0%, 22%, 0.15);
65
@box-shadow: @box-shadow-border, @box-shadow-common;
@@ -54,7 +53,7 @@
5453
flex-grow: 1;
5554
align-items: center;
5655
padding: 16px 24px;
57-
background-color: @background-color;
56+
background-color: @component-background;
5857
box-shadow: @box-shadow;
5958
outline: none;
6059
border-radius: 4px;

packages/sortable-list/src/BaseItem/index.tsx renamed to packages/sortable-list/src/components/BaseItem/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import type { CSSProperties } from 'react';
22
import React, { forwardRef, memo, useEffect } from 'react';
33
import classNames from 'classnames';
44

5-
import { Handle, Remove } from '../components';
5+
import { Handle } from '../Handle';
6+
import { Remove } from '../Remove';
67

7-
import type { BaseItemProps } from '../types';
8+
import type { BaseItemProps } from '../../types';
89

910
import './index.less';
1011

packages/sortable-list/src/DraggingOverlay.tsx renamed to packages/sortable-list/src/components/DraggingOverlay.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DragOverlay } from '@dnd-kit/core';
33
import { Item } from './BaseItem';
44
import type { FC } from 'react';
55

6-
import type { DraggingOverlayProps } from './types';
6+
import type { DraggingOverlayProps } from '../types';
77

88
const DraggingOverlay: FC<DraggingOverlayProps> = ({
99
dragging,
@@ -15,7 +15,6 @@ const DraggingOverlay: FC<DraggingOverlayProps> = ({
1515
getItemStyles,
1616
getWrapperStyle,
1717
activeIndex,
18-
activeId,
1918
}) => {
2019
return (
2120
<DragOverlay adjustScale={adjustScale} dropAnimation={dropAnimation}>
@@ -32,7 +31,7 @@ const DraggingOverlay: FC<DraggingOverlayProps> = ({
3231
style={getItemStyles({
3332
id: item.id,
3433
index: activeIndex,
35-
isSorting: activeId !== null,
34+
isSorting: true,
3635
isDragging: true,
3736
overIndex: -1,
3837
isDragOverlay: true,

packages/sortable-list/src/SortableItem.tsx renamed to packages/sortable-list/src/components/SortableItem.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
/* istanbul ignore file */
12
import type { FC } from 'react';
23
import React from 'react';
34

45
import { useSortable } from '@dnd-kit/sortable';
56

67
import { Item } from './BaseItem';
7-
import type { SortableItemProps } from './types';
8+
import type { SortableItemProps } from '../types';
89

910
const SortableItem: FC<SortableItemProps> = ({
1011
//数据
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { Action } from './Action';
22
export { Handle } from './Handle';
33
export { Remove } from './Remove';
4+
export { Item } from './BaseItem';

packages/sortable-list/src/Sortable.tsx renamed to packages/sortable-list/src/container/App.tsx

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,28 @@ import {
2020
} from '@dnd-kit/sortable';
2121
import { Flexbox } from '@arvinxu/layout-kit';
2222

23-
import SortableItem from './SortableItem';
24-
import DraggingOverlay from './DraggingOverlay';
23+
import SortableItem from '../components/SortableItem';
24+
import DraggingOverlay from '../components/DraggingOverlay';
2525

26-
import type { SortableProps } from './types';
26+
import type { SortableProps, SortableListStore } from '../types';
2727

28-
import { useSortableList } from './hooks/useSortableList';
29-
import { useActiveItem } from './hooks/useActiveItem';
30-
import { getIndexOfActiveItem } from './utils';
28+
import { useStore } from '../store';
29+
import { getIndexOfActiveItem } from '../store/utils';
30+
31+
const dataSelector = (s: SortableListStore) => s.data;
32+
33+
const activeSelector = (s: SortableListStore) => ({
34+
isDragging: s.activeId !== null,
35+
activeIndex: getIndexOfActiveItem(s.data, s.activeId),
36+
});
37+
38+
const actionSelector = (s: SortableListStore) => ({
39+
deactivateItem: s.deactivateItem,
40+
activateItem: s.activateItem,
41+
reorder: s.reorder,
42+
removeItem: s.removeItem,
43+
addItem: s.addItem,
44+
});
3145

3246
const Wrapper: FC<{
3347
style?: CSSProperties;
@@ -44,9 +58,6 @@ const Wrapper: FC<{
4458
);
4559

4660
export const Sortable: FC<SortableProps> = ({
47-
//数据
48-
items: controlledItems,
49-
onItemChange,
5061
// 方法
5162
strategy,
5263
renderItem,
@@ -85,24 +96,19 @@ export const Sortable: FC<SortableProps> = ({
8596
}),
8697
);
8798

88-
const { items, dispatchSortable } = useSortableList({
89-
value: controlledItems,
90-
onChange: onItemChange,
91-
});
92-
93-
const { deactivateItem, activateItem, activeId, isDragging } =
94-
useActiveItem();
95-
96-
const activeIndex = getIndexOfActiveItem(items, activeId);
99+
const items = useStore(dataSelector);
100+
const { activeIndex, isDragging } = useStore(activeSelector);
101+
const { deactivateItem, activateItem, reorder, addItem, removeItem } =
102+
useStore(actionSelector);
97103

98104
const handleRemove = (id: string) => {
99105
if (!removable) return;
100106

101-
dispatchSortable({ type: 'removeItem', id });
107+
removeItem(id);
102108
};
103109

104110
const handleAddItem = (index: number, item: any) => {
105-
dispatchSortable({ type: 'addItem', item, addIndex: index });
111+
addItem(item, index);
106112
};
107113
return (
108114
// 最外层的 DndContext
@@ -118,11 +124,7 @@ export const Sortable: FC<SortableProps> = ({
118124
if (over) {
119125
const endIndex = getIndexOfActiveItem(items, over.id);
120126

121-
dispatchSortable({
122-
type: 'reorder',
123-
startIndex: activeIndex,
124-
endIndex,
125-
});
127+
reorder(activeIndex, endIndex);
126128
}
127129
deactivateItem();
128130
}}
@@ -168,7 +170,6 @@ export const Sortable: FC<SortableProps> = ({
168170
adjustScale={adjustScale}
169171
dropAnimation={dropAnimation}
170172
dragging={isDragging}
171-
activeId={activeId}
172173
activeIndex={activeIndex}
173174
item={items[activeIndex]}
174175
getItemStyles={getItemStyles}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useStoreUpdater } from '../hooks/useStoreUpdater';
2+
import type { StoreUpdaterProps } from '../types';
3+
4+
const StoreUpdater = (props: StoreUpdaterProps) => {
5+
useStoreUpdater(props);
6+
7+
return null;
8+
};
9+
10+
export default StoreUpdater;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import type { FC } from 'react';
3+
4+
import { Provider, createStore, useStoreApi } from '../store';
5+
6+
const StoreWrapper: FC = ({ children }) => {
7+
let isWrapped = true;
8+
9+
try {
10+
useStoreApi();
11+
} catch (e) {
12+
isWrapped = false;
13+
}
14+
15+
if (isWrapped) {
16+
// we need to wrap it with a fragment because it's not allowed for children to be a ReactNode
17+
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
18+
return <>{children}</>;
19+
}
20+
21+
return <Provider createStore={createStore}>{children}</Provider>;
22+
};
23+
24+
export default StoreWrapper;

packages/sortable-list/src/index.tsx renamed to packages/sortable-list/src/container/index.tsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import {
1414
restrictToWindowEdges,
1515
} from '@dnd-kit/modifiers';
1616

17-
import { Sortable } from './Sortable';
18-
import type { SortableItemList, SortableListProps } from './types';
17+
import { Sortable } from './App';
18+
import type { SortableItemList, SortableListProps } from '../types';
19+
import StoreWrapper from './Wrapper';
20+
import StoreUpdater from './StoreUpdater';
1921

2022
const defaultDropAnimationConfig: DropAnimation = {
2123
...defaultDropAnimation,
@@ -75,26 +77,21 @@ function SortableList<T extends SortableItemList = SortableItemList>({
7577
}, [direction, getModifiers]);
7678

7779
return (
78-
<Sortable
79-
direction={direction}
80-
items={dataSource}
81-
onItemChange={onChange}
82-
dropAnimation={defaultDropAnimationConfig}
83-
renderItem={renderItem}
84-
removable={removable}
85-
{...config}
86-
style={style}
87-
getItemStyles={getItemStyles}
88-
className={className}
89-
gap={gap}
90-
/>
80+
<StoreWrapper>
81+
<Sortable
82+
direction={direction}
83+
dropAnimation={defaultDropAnimationConfig}
84+
renderItem={renderItem}
85+
removable={removable}
86+
{...config}
87+
style={style}
88+
getItemStyles={getItemStyles}
89+
className={className}
90+
gap={gap}
91+
/>
92+
<StoreUpdater onDataChange={onChange} data={dataSource} />
93+
</StoreWrapper>
9194
);
9295
}
9396

9497
export default SortableList;
95-
96-
export type {
97-
SortableBaseItem,
98-
SortableItemList,
99-
SortableListProps,
100-
} from './types';

packages/sortable-list/src/hooks/useActiveItem.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)