Skip to content

Commit

Permalink
🐛 fix: 重构并修复 setData 值时会出现的重复渲染卡死的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx authored Mar 8, 2022
2 parents 13bdaeb + 2e812bc commit a3b31f5
Show file tree
Hide file tree
Showing 31 changed files with 681 additions and 385 deletions.
3 changes: 2 additions & 1 deletion packages/sortable-list/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"@dnd-kit/core": "^5.0.1",
"@dnd-kit/modifiers": "^5.0.0",
"@dnd-kit/sortable": "^6.0.0",
"antd": "^4.18.9",
"classnames": "^2.3.1",
"lodash.isequal": "^4.5.0",
"use-merge-value": "^1.0.2"
"zustand": "^3.7.1"
}
}
8 changes: 0 additions & 8 deletions packages/sortable-list/src/components/Action/index.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
@focused-outline-color: #4c9ffe;

.Action {
display: flex;
width: 12px;
Expand Down Expand Up @@ -41,10 +39,4 @@
fill: var(--fill, #788491);
}
}

&:focus-visible {
outline: none;
box-shadow: 0 0 0 2px rgba(255, 255, 255, 0),
0 0px 0px 2px @focused-outline-color;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
@background-color: #fff;
@border-color: #efefef;
@handle-color: rgba(0, 0, 0, 0.25);
@import (reference) '~antd/es/style/themes/default.less';

@box-shadow-border: 0 0 0 calc(1px / var(--scale-x, 1)) hsla(240, 0%, 26%, 0.05);
@box-shadow-common: 0 1px calc(3px / var(--scale-x, 1)) hsla(240, 0%, 22%, 0.15);
@box-shadow: @box-shadow-border, @box-shadow-common;
Expand Down Expand Up @@ -54,7 +53,7 @@
flex-grow: 1;
align-items: center;
padding: 16px 24px;
background-color: @background-color;
background-color: @component-background;
box-shadow: @box-shadow;
outline: none;
border-radius: 4px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import type { CSSProperties } from 'react';
import React, { forwardRef, memo, useEffect } from 'react';
import classNames from 'classnames';

import { Handle, Remove } from '../components';
import { Handle } from '../Handle';
import { Remove } from '../Remove';

import type { BaseItemProps } from '../types';
import type { BaseItemProps } from '../../types';

import './index.less';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DragOverlay } from '@dnd-kit/core';
import { Item } from './BaseItem';
import type { FC } from 'react';

import type { DraggingOverlayProps } from './types';
import type { DraggingOverlayProps } from '../types';

const DraggingOverlay: FC<DraggingOverlayProps> = ({
dragging,
Expand All @@ -15,7 +15,6 @@ const DraggingOverlay: FC<DraggingOverlayProps> = ({
getItemStyles,
getWrapperStyle,
activeIndex,
activeId,
}) => {
return (
<DragOverlay adjustScale={adjustScale} dropAnimation={dropAnimation}>
Expand All @@ -32,7 +31,7 @@ const DraggingOverlay: FC<DraggingOverlayProps> = ({
style={getItemStyles({
id: item.id,
index: activeIndex,
isSorting: activeId !== null,
isSorting: true,
isDragging: true,
overIndex: -1,
isDragOverlay: true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/* istanbul ignore file */
import type { FC } from 'react';
import React from 'react';

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

import { Item } from './BaseItem';
import type { SortableItemProps } from './types';
import type { SortableItemProps } from '../types';

const SortableItem: FC<SortableItemProps> = ({
//数据
Expand Down
1 change: 1 addition & 0 deletions packages/sortable-list/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { Action } from './Action';
export { Handle } from './Handle';
export { Remove } from './Remove';
export { Item } from './BaseItem';
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,28 @@ import {
} from '@dnd-kit/sortable';
import { Flexbox } from '@arvinxu/layout-kit';

import SortableItem from './SortableItem';
import DraggingOverlay from './DraggingOverlay';
import SortableItem from '../components/SortableItem';
import DraggingOverlay from '../components/DraggingOverlay';

import type { SortableProps } from './types';
import type { SortableProps, SortableListStore } from '../types';

import { useSortableList } from './hooks/useSortableList';
import { useActiveItem } from './hooks/useActiveItem';
import { getIndexOfActiveItem } from './utils';
import { useStore } from '../store';
import { getIndexOfActiveItem } from '../store/utils';

const dataSelector = (s: SortableListStore) => s.data;

const activeSelector = (s: SortableListStore) => ({
isDragging: s.activeId !== null,
activeIndex: getIndexOfActiveItem(s.data, s.activeId),
});

const actionSelector = (s: SortableListStore) => ({
deactivateItem: s.deactivateItem,
activateItem: s.activateItem,
reorder: s.reorder,
removeItem: s.removeItem,
addItem: s.addItem,
});

const Wrapper: FC<{
style?: CSSProperties;
Expand All @@ -44,9 +58,6 @@ const Wrapper: FC<{
);

export const Sortable: FC<SortableProps> = ({
//数据
items: controlledItems,
onItemChange,
// 方法
strategy,
renderItem,
Expand Down Expand Up @@ -85,24 +96,19 @@ export const Sortable: FC<SortableProps> = ({
}),
);

const { items, dispatchSortable } = useSortableList({
value: controlledItems,
onChange: onItemChange,
});

const { deactivateItem, activateItem, activeId, isDragging } =
useActiveItem();

const activeIndex = getIndexOfActiveItem(items, activeId);
const items = useStore(dataSelector);
const { activeIndex, isDragging } = useStore(activeSelector);
const { deactivateItem, activateItem, reorder, addItem, removeItem } =
useStore(actionSelector);

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

dispatchSortable({ type: 'removeItem', id });
removeItem(id);
};

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

dispatchSortable({
type: 'reorder',
startIndex: activeIndex,
endIndex,
});
reorder(activeIndex, endIndex);
}
deactivateItem();
}}
Expand Down Expand Up @@ -168,7 +170,6 @@ export const Sortable: FC<SortableProps> = ({
adjustScale={adjustScale}
dropAnimation={dropAnimation}
dragging={isDragging}
activeId={activeId}
activeIndex={activeIndex}
item={items[activeIndex]}
getItemStyles={getItemStyles}
Expand Down
10 changes: 10 additions & 0 deletions packages/sortable-list/src/container/StoreUpdater.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useStoreUpdater } from '../hooks/useStoreUpdater';
import type { StoreUpdaterProps } from '../types';

const StoreUpdater = (props: StoreUpdaterProps) => {
useStoreUpdater(props);

return null;
};

export default StoreUpdater;
24 changes: 24 additions & 0 deletions packages/sortable-list/src/container/Wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import type { FC } from 'react';

import { Provider, createStore, useStoreApi } from '../store';

const StoreWrapper: FC = ({ children }) => {
let isWrapped = true;

try {
useStoreApi();
} catch (e) {
isWrapped = false;
}

if (isWrapped) {
// we need to wrap it with a fragment because it's not allowed for children to be a ReactNode
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051
return <>{children}</>;
}

return <Provider createStore={createStore}>{children}</Provider>;
};

export default StoreWrapper;
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import {
restrictToWindowEdges,
} from '@dnd-kit/modifiers';

import { Sortable } from './Sortable';
import type { SortableItemList, SortableListProps } from './types';
import { Sortable } from './App';
import type { SortableItemList, SortableListProps } from '../types';
import StoreWrapper from './Wrapper';
import StoreUpdater from './StoreUpdater';

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

return (
<Sortable
direction={direction}
items={dataSource}
onItemChange={onChange}
dropAnimation={defaultDropAnimationConfig}
renderItem={renderItem}
removable={removable}
{...config}
style={style}
getItemStyles={getItemStyles}
className={className}
gap={gap}
/>
<StoreWrapper>
<Sortable
direction={direction}
dropAnimation={defaultDropAnimationConfig}
renderItem={renderItem}
removable={removable}
{...config}
style={style}
getItemStyles={getItemStyles}
className={className}
gap={gap}
/>
<StoreUpdater onDataChange={onChange} data={dataSource} />
</StoreWrapper>
);
}

export default SortableList;

export type {
SortableBaseItem,
SortableItemList,
SortableListProps,
} from './types';
17 changes: 0 additions & 17 deletions packages/sortable-list/src/hooks/useActiveItem.ts

This file was deleted.

Loading

1 comment on commit a3b31f5

@vercel
Copy link

@vercel vercel bot commented on a3b31f5 Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.