Skip to content

Commit

Permalink
Merge pull request #2708 from udecode/feat/hoc-optimisation
Browse files Browse the repository at this point in the history
Improve performance of placeholder and draggable HOCs
  • Loading branch information
zbeyens authored Oct 19, 2023
2 parents b485a19 + cf83eb6 commit 43ea4c1
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-candles-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@udecode/plate-dnd': patch
---

Reduce performance overhead of draggable component
5 changes: 5 additions & 0 deletions .changeset/new-coins-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@udecode/plate-utils': patch
---

Do not re-render placeholder on every editor change
30 changes: 21 additions & 9 deletions apps/www/src/registry/default/plate-ui/draggable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,28 @@ export interface DraggableProps
) => boolean;
}

const dragHandle = (
<Tooltip>
<TooltipTrigger>
<Icons.dragHandle className="h-4 w-4 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>Drag to move</TooltipContent>
</Tooltip>
);

const Draggable = forwardRef<HTMLDivElement, DraggableProps>(
({ className, classNames = {}, onDropHandler, ...props }, ref) => {
const { children, element } = props;

const state = useDraggableState({ element, onDropHandler });
const { dropLine, isDragging } = state;
const { droplineProps, gutterLeftProps, previewRef, handleRef } =
useDraggable(state);
const { dropLine, isDragging, isHovered } = state;
const {
groupProps,
droplineProps,
gutterLeftProps,
previewRef,
handleRef,
} = useDraggable(state);

return (
<div
Expand All @@ -95,6 +109,7 @@ const Draggable = forwardRef<HTMLDivElement, DraggableProps>(
className
)}
ref={ref}
{...groupProps}
>
<div
className={cn(
Expand All @@ -110,12 +125,9 @@ const Draggable = forwardRef<HTMLDivElement, DraggableProps>(
classNames.blockToolbar
)}
>
<Tooltip>
<TooltipTrigger ref={handleRef}>
<Icons.dragHandle className="h-4 w-4 text-muted-foreground" />
</TooltipTrigger>
<TooltipContent>Drag to move</TooltipContent>
</Tooltip>
<div ref={handleRef} className="h-4 w-4">
{isHovered && dragHandle}
</div>
</div>
</div>
</div>
Expand Down
18 changes: 16 additions & 2 deletions packages/dnd/src/components/useDraggable.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React, { useRef } from 'react';
import React, { useRef, useState } from 'react';
import { TEditor, TElement } from '@udecode/plate-common';
import { ConnectDragSource, DropTargetMonitor } from 'react-dnd';

import { DragItemNode, DropLineDirection, useDndBlock } from '..';

export type DraggableState = {
dropLine: DropLineDirection;
isHovered: boolean;
setIsHovered: (isHovered: boolean) => void;
isDragging: boolean;
nodeRef: React.RefObject<HTMLDivElement>;
dragRef: ConnectDragSource;
Expand All @@ -26,19 +28,31 @@ export const useDraggableState = (props: {
const { element, onDropHandler } = props;

const nodeRef = useRef<HTMLDivElement>(null);
const [isHovered, setIsHovered] = useState(false);
const { dropLine, isDragging, dragRef } = useDndBlock({
id: element.id as string,
nodeRef,
onDropHandler,
});

return { dropLine, isDragging, nodeRef, dragRef };
return {
dropLine,
isHovered,
setIsHovered,
isDragging,
nodeRef,
dragRef,
};
};

export const useDraggable = (state: DraggableState) => {
return {
previewRef: state.nodeRef,
handleRef: state.dragRef,
groupProps: {
onPointerEnter: () => state.setIsHovered(true),
onPointerLeave: () => state.setIsHovered(false),
},
droplineProps: {
contentEditable: false,
},
Expand Down
4 changes: 2 additions & 2 deletions packages/plate-utils/src/hooks/usePlaceholder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEditorState } from '@udecode/plate-core';
import { useEditorRef } from '@udecode/plate-core';
import {
isCollapsed,
isElementEmpty,
Expand All @@ -23,7 +23,7 @@ export const usePlaceholderState = ({
}: PlaceholderProps) => {
const focused = useFocused();
const selected = useSelected();
const editor = useEditorState();
const editor = useEditorRef();

const isEmptyBlock = isElementEmpty(editor, element);

Expand Down

0 comments on commit 43ea4c1

Please sign in to comment.