@atlaskit/pragmatic-drag-and-drop-docs
Version:
This package holds the documentation for Pragmatic drag and drop in one place. It is not intended to be consumed directly by consumers. The package is used by other tools for sharing examples
193 lines (155 loc) • 4.86 kB
text/mdx
---
title: Reconciliation
description: How Pragmatic drag and drop reconciles pieces.
order: 0
---
The `key` for a _drop target_ is the element. At any one time, only a single _drop target_ for a
particular entity type (eg files) can be attached to the same element.
```ts
// ✅ Using the same element as a drop target for elements and for files
const cleanup = combine(
dropTargetForElements({
element: myElement,
}),
dropTargetForExternal({
element: myElement,
}),
);
```
```ts
// ❌ Using the same element for two drop targets of the same entity type is not allowed
const cleanup = combine(
dropTargetForElements({
element: myElement,
}),
// ⚠️ A warning will be logged if this is detected
dropTargetForElements({
element: myElement,
}),
);
```
During a drag operation, if a _drop target_ is removed and readded on the same `element`, then
`@atlaskit/pragmatic-drag-and-drop` will treat the added _drop target_ as if it was the same _drop
target_.
```ts
const monitor = monitorForElements({
onDragStart: () => console.log('monitor:start'),
onDropTargetChange: () => console.log('monitor:change'),
onDrop: () => console.log('monitor:drop'),
});
const cleanup1 = dropTargetForElements({
element: A,
onDragStart: () => console.log('A1:start'),
onDropTargetChange: () => console.log('A1:change'),
onDrop: () => console.log('A1:drop'),
});
// a drag starts
// console.log → 'A1:start', 'monitor:start'
// drop target is removed during a drag
cleanup1();
// console.log not called (no change event is fired)
const cleanup2 = dropTargetForElements({
element: A,
onDragStart: () => console.log('A2:start'),
onDropTargetChange: () => console.log('A2:change'),
onDrop: () => console.log('A2:drop'),
});
// a dragover occurs
// console.log → 'A2:drag', 'monitor:drag'
// 👆 note: no 'change' event occured, A2 is treated as A1
```
The `key` for a `draggable` is the element. An element can only be used for a single `draggable`.
```ts
// ❌ Using the same element for two draggables
draggable({
element: myElement,
}),
// ⚠️ A warning will be logged if this is detected
draggable({
element: myElement,
}),
);
```
During a drag operation, if the dragging `draggable` is removed and readded on the same `element`,
then `@atlaskit/pragmatic-drag-and-drop` will treat the added `draggable` as if it was the original
`draggable`.
```ts
const monitor = monitorForElements({
onDragStart: () => console.log('monitor:start'),
onDrop: () => console.log('monitor:drop'),
});
const cleanup1 = draggable({
element: A,
onDragStart: () => console.log('A1:start'),
onDrop: () => console.log('A1:drop'),
});
// a drag starts
// console.log → 'A1:start', 'monitor:start'
// drop target is removed during a drag
cleanup1();
// console.log not called (no change event is fired)
const cleanup2 = dropTargetForElements({
element: A,
onDragStart: () => console.log('A2:start'),
onDrop: () => console.log('A2:drop'),
});
// a drop occurs
// console.log → 'A2:drop', 'monitor:drop'
// 👆 note: the drop event occured on 'A2' even though it was not the same `draggable()` as the original drag
```
Remounting a `draggable` common in `react` where you _might_ do something like this:
```tsx
function Card() {
const ref = useRef();
const [dragCount, setCount] = useState(0);
useEffect(() => {
return draggable({
element,
onDragStart: () => setCount(dragCount + 1),
});
// when dragCount changes our `draggable` will be remounted
}, [dragCount]);
return <div ref={ref}>I have been dragged {dragCount} times</div>;
}
```
This is a contrived example, because you _could_ avoid the remounting in this case by doing this:
```tsx
function Card() {
const ref = useRef();
const [dragCount, setCount] = useState(0);
useEffect(() => {
return draggable({
element,
onDragStart: () => setCount((current) => current + 1),
});
// no longer need to remount when `dragCount` changes
}, []);
return <div ref={ref}>I have been dragged {dragCount} times</div>;
}
```
Each call to create a _monitor_ will create a new monitor, even if the monitor definition is shared.
There is no `key` for _monitors_.
```ts
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
const args = {
onGenerateDragPreview: () => console.log('monitor:preview'),
};
// these two monitors are sharing the same `args` reference
// but they will both create an independent monitor
const cleanup1 = monitorForElements(args);
const cleanup2 = monitorForElements(args);
// → A drag starts
// console.log:
// - 'monitor:preview'
// - 'monitor:preview'
// → A drag finishes
// removing one monitor
cleanup1();
// → Another drag starts
// console.log:
// - 'monitor:preview'
// 👆 one monitor is still active
```