feat: optimization of render during dnd
This commit is contained in:
21
src/app/deals/components/DealContainer/DealContainer.tsx
Normal file
21
src/app/deals/components/DealContainer/DealContainer.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import React, { FC, useMemo } from "react";
|
||||||
|
import { Box } from "@mantine/core";
|
||||||
|
import DealCard from "@/app/deals/components/DealCard/DealCard";
|
||||||
|
import { SortableItem } from "@/components/SortableDnd/SortableItem";
|
||||||
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
deal: DealSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DealContainer: FC<Props> = ({ deal }) => {
|
||||||
|
const dealBody = useMemo(() => <DealCard deal={deal} />, [deal]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<SortableItem id={deal.id}>{dealBody}</SortableItem>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DealContainer;
|
||||||
@ -5,23 +5,44 @@ import {
|
|||||||
verticalListSortingStrategy,
|
verticalListSortingStrategy,
|
||||||
} from "@dnd-kit/sortable";
|
} from "@dnd-kit/sortable";
|
||||||
import { Box, Stack, Text } from "@mantine/core";
|
import { Box, Stack, Text } from "@mantine/core";
|
||||||
import DealCard from "@/app/deals/components/DealCard/DealCard";
|
import DealContainer from "@/app/deals/components/DealContainer/DealContainer";
|
||||||
import { SortableItem } from "@/components/SortableDnd/SortableItem";
|
|
||||||
import { DealSchema } from "@/types/DealSchema";
|
import { DealSchema } from "@/types/DealSchema";
|
||||||
|
import { StatusSchema } from "@/types/StatusSchema";
|
||||||
import { sortByLexorank } from "@/utils/lexorank";
|
import { sortByLexorank } from "@/utils/lexorank";
|
||||||
|
|
||||||
type BoardSectionProps = {
|
type BoardSectionProps = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
status: StatusSchema;
|
||||||
deals: DealSchema[];
|
deals: DealSchema[];
|
||||||
isDragging?: boolean;
|
isDragging?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StatusColumn = ({ id, title, deals, isDragging }: BoardSectionProps) => {
|
const StatusColumn = ({ id, status, deals, isDragging }: BoardSectionProps) => {
|
||||||
const { setNodeRef } = useDroppable({ id });
|
const { setNodeRef } = useDroppable({ id });
|
||||||
const sortedDeals = useMemo(() => sortByLexorank(deals), [deals]);
|
const sortedDeals = useMemo(
|
||||||
|
() => sortByLexorank(deals.filter(deal => deal.statusId === status.id)),
|
||||||
|
[deals]
|
||||||
|
);
|
||||||
|
|
||||||
console.log("rerender");
|
const columnBody = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<SortableContext
|
||||||
|
id={id}
|
||||||
|
items={sortedDeals}
|
||||||
|
strategy={verticalListSortingStrategy}>
|
||||||
|
<Stack
|
||||||
|
gap={"xs"}
|
||||||
|
ref={setNodeRef}>
|
||||||
|
{sortedDeals.map(deal => (
|
||||||
|
<DealContainer
|
||||||
|
key={deal.id}
|
||||||
|
deal={deal}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</SortableContext>
|
||||||
|
);
|
||||||
|
}, [sortedDeals]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -37,24 +58,9 @@ const StatusColumn = ({ id, title, deals, isDragging }: BoardSectionProps) => {
|
|||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
opacity: isDragging ? 0.5 : 1,
|
opacity: isDragging ? 0.5 : 1,
|
||||||
}}>
|
}}>
|
||||||
{title}
|
{status.name}
|
||||||
</Text>
|
</Text>
|
||||||
<SortableContext
|
{columnBody}
|
||||||
id={id}
|
|
||||||
items={sortedDeals}
|
|
||||||
strategy={verticalListSortingStrategy}>
|
|
||||||
<Stack
|
|
||||||
gap={"xs"}
|
|
||||||
ref={setNodeRef}>
|
|
||||||
{sortedDeals.map(deal => (
|
|
||||||
<Box key={deal.id}>
|
|
||||||
<SortableItem id={deal.id}>
|
|
||||||
<DealCard deal={deal} />
|
|
||||||
</SortableItem>
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Stack>
|
|
||||||
</SortableContext>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,7 +19,14 @@ const StatusColumns = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return <StatusColumnsDnd onDealDragEnd={onDealDragEnd} />;
|
const onStatusDragEnd = (statusId: number, lexorank: string) => {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StatusColumnsDnd
|
||||||
|
onDealDragEnd={onDealDragEnd}
|
||||||
|
onStatusDragEnd={onStatusDragEnd}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default StatusColumns;
|
export default StatusColumns;
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
KeyboardSensor,
|
KeyboardSensor,
|
||||||
Over,
|
Over,
|
||||||
PointerSensor,
|
PointerSensor,
|
||||||
|
TouchSensor,
|
||||||
useSensor,
|
useSensor,
|
||||||
useSensors,
|
useSensors,
|
||||||
} from "@dnd-kit/core";
|
} from "@dnd-kit/core";
|
||||||
@ -36,25 +37,36 @@ type Props = {
|
|||||||
statusId: number,
|
statusId: number,
|
||||||
lexorank?: string
|
lexorank?: string
|
||||||
) => void;
|
) => void;
|
||||||
onStatusDragEnd?: (statusId: number, newRank: string) => void;
|
onStatusDragEnd: (statusId: number, lexorank: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StatusColumnsDnd: FC<Props> = props => {
|
const StatusColumnsDnd: FC<Props> = props => {
|
||||||
const { statuses, deals, setDeals, setStatuses } = useStatusesContext();
|
const { statuses, deals, setDeals, setStatuses } = useStatusesContext();
|
||||||
const [activeDeal, setActiveDeal] = useState<DealSchema | null>(null);
|
const [activeDeal, setActiveDeal] = useState<DealSchema | null>(null);
|
||||||
const [activeStatus, setActiveStatus] = useState<StatusSchema | null>(null);
|
const [activeStatus, setActiveStatus] = useState<StatusSchema | null>(null);
|
||||||
|
|
||||||
const sortedStatuses = useMemo(() => sortByLexorank(statuses), [statuses]);
|
const sortedStatuses = useMemo(() => sortByLexorank(statuses), [statuses]);
|
||||||
|
|
||||||
|
const throttledSetStatuses = useMemo(
|
||||||
|
() => throttle(setStatuses, 200),
|
||||||
|
[setStatuses]
|
||||||
|
);
|
||||||
const throttledSetDeals = useMemo(
|
const throttledSetDeals = useMemo(
|
||||||
() => throttle(setDeals, 200),
|
() => throttle(setDeals, 200),
|
||||||
[setDeals]
|
[setDeals]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sensorOptions = {
|
||||||
|
activationConstraint: {
|
||||||
|
distance: 5,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(PointerSensor),
|
useSensor(PointerSensor, sensorOptions),
|
||||||
useSensor(KeyboardSensor, {
|
useSensor(KeyboardSensor, {
|
||||||
coordinateGetter: sortableKeyboardCoordinates,
|
coordinateGetter: sortableKeyboardCoordinates,
|
||||||
})
|
}),
|
||||||
|
useSensor(TouchSensor, sensorOptions)
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDragStart = ({ active }: DragStartEvent) => {
|
const handleDragStart = ({ active }: DragStartEvent) => {
|
||||||
@ -131,7 +143,7 @@ const StatusColumnsDnd: FC<Props> = props => {
|
|||||||
const newRank = getNewStatusRank(activeStatusId, overStatusId);
|
const newRank = getNewStatusRank(activeStatusId, overStatusId);
|
||||||
if (!newRank) return;
|
if (!newRank) return;
|
||||||
|
|
||||||
setStatuses(statuses =>
|
throttledSetStatuses(statuses =>
|
||||||
statuses.map(status =>
|
statuses.map(status =>
|
||||||
status.id === activeStatusId
|
status.id === activeStatusId
|
||||||
? { ...status, rank: newRank }
|
? { ...status, rank: newRank }
|
||||||
@ -317,10 +329,8 @@ const StatusColumnsDnd: FC<Props> = props => {
|
|||||||
id={`${status.id}-status`}>
|
id={`${status.id}-status`}>
|
||||||
<StatusColumn
|
<StatusColumn
|
||||||
id={`${status.id}-status`}
|
id={`${status.id}-status`}
|
||||||
title={status.name}
|
status={status}
|
||||||
deals={deals.filter(
|
deals={deals}
|
||||||
deal => deal.statusId === status.id
|
|
||||||
)}
|
|
||||||
isDragging={activeStatus?.id === status.id}
|
isDragging={activeStatus?.id === status.id}
|
||||||
/>
|
/>
|
||||||
</SortableItem>
|
</SortableItem>
|
||||||
@ -332,7 +342,7 @@ const StatusColumnsDnd: FC<Props> = props => {
|
|||||||
) : activeStatus ? (
|
) : activeStatus ? (
|
||||||
<StatusColumn
|
<StatusColumn
|
||||||
id={`${activeStatus.id}-status`}
|
id={`${activeStatus.id}-status`}
|
||||||
title={activeStatus.name}
|
status={activeStatus}
|
||||||
deals={deals.filter(
|
deals={deals.filter(
|
||||||
deal =>
|
deal =>
|
||||||
deal.statusId ===
|
deal.statusId ===
|
||||||
|
|||||||
Reference in New Issue
Block a user