Skip to content

Commit

Permalink
fix: repair the DND example
Browse files Browse the repository at this point in the history
Fixes #993
  • Loading branch information
petyosi committed Oct 16, 2023
1 parent a2384c6 commit 12e53e5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 60 deletions.
125 changes: 66 additions & 59 deletions docs/scenarios/react-beautiful-dnd.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,70 +5,56 @@ sidebar_label: React Beautiful DND
slug: /react-beautiful-dnd/
---

The example below integrates React Virtuoso with [React Beautiful DND](https://github.com/atlassian/react-beautiful-dnd).
The example below integrates React Virtuoso with the maintained fork of [React Beautiful DND](https://github.com/atlassian/react-beautiful-dnd), [hello-pangea/dnd](https://github.com/hello-pangea/dnd).
The example works with Beautiful DND too, but causes warnings with StrictMode.

```jsx live import=react-beautiful-dnd
import React, { useCallback, useEffect, useState } from 'react'
import ReactDOM from 'react-dom'
import { Virtuoso } from 'react-virtuoso'
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd'
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import { Virtuoso } from "react-virtuoso";
// Works with react-beautiful-dnd, too, but causes issues with StrictMode
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";

// Virtuoso's resize observer can this error,
// which is caught by DnD and aborts dragging.
window.addEventListener('error', (e) => {
if (e.message === 'ResizeObserver loop completed with undelivered notifications.' || e.message === 'ResizeObserver loop limit exceeded') {
e.stopImmediatePropagation()
window.addEventListener("error", (e) => {
if (
e.message ===
"ResizeObserver loop completed with undelivered notifications." ||
e.message === "ResizeObserver loop limit exceeded"
) {
e.stopImmediatePropagation();
}
})
});

// Generate our initial big data set
const initial = Array.from({ length: 1000 }, (_, k) => ({
id: `id:${k}`,
text: `item ${k}`,
}))
text: `item ${k}`
}));

function reorder(list, startIndex, endIndex) {
const result = Array.from(list)
const [removed] = result.splice(startIndex, 1)
result.splice(endIndex, 0, removed)
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);

return result
return result;
}

function Item({ provided, item, isDragging }) {
return (
<div style={{ paddingBottom: '8px' }}>
<div style={{ paddingBottom: "8px" }}>
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
style={provided.draggableProps.style}
className={`item ${isDragging ? 'is-dragging' : ''}`}
className={`item ${isDragging ? "is-dragging" : ""}`}
>
{item.text}
</div>
</div>
)
}

const HeightPreservingItem = ({ children, ...props }) => {
const [size, setSize] = useState(0)
const knownSize = props['data-known-size']
useEffect(() => {
setSize((prevSize) => {
return knownSize == 0 ? prevSize : knownSize
})
}, [knownSize])
return (
<div
{...props}
className="height-preserving-container"
// check styling in the style tag below
style={{ '--child-height': `${size}px`, }}
>
{children}
</div>
)
);
}

export default function App() {
Expand All @@ -89,46 +75,67 @@ export default function App() {
[setItems]
)

const HeightPreservingItem = React.useCallback(({ children, ...props }) => {
const [size, setSize] = useState(0);
const knownSize = props["data-known-size"];
useEffect(() => {
setSize((prevSize) => {
return knownSize == 0 ? prevSize : knownSize;
});
}, [knownSize]);
return (
<div
{...props}
className="height-preserving-container"
style={{
"--child-height": `${size}px`
}}
>
{children}
</div>
);
}, []);

return (
<div style={{ padding: '1rem' }}>
<style>
{`
.height-preserving-container:empty {
min-height: calc(var(--child-height));
box-sizing: border-box;
}
`}
</style>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable
droppableId="droppable"
mode="virtual"
renderClone={(provided, snapshot, rubric) => (
<Item provided={provided} isDragging={snapshot.isDragging} item={items[rubric.source.index]} />
)}
>
{`
.height-preserving-container:empty {
min-height: calc(var(--child-height));
box-sizing: border-box;
}
`}
</style>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable
droppableId="droppable"
mode="virtual"
renderClone={(provided, snapshot, rubric) => (
<Item provided={provided} isDragging={snapshot.isDragging} item={items[rubric.source.index]} />
)}
>
{(provided) => {
return (
<Virtuoso
components={{
Item: HeightPreservingItem,
Item: HeightPreservingItem
}}
scrollerRef={provided.innerRef}
data={items}
style={{ width: 300, height: 500 }}
itemContent={(index, item) => {
return (
<Draggable draggableId={item.id} index={index} key={item.id}>
{(provided) => <Item provided={provided} item={item} isDragging={false} />}
<Draggable draggableId={item.id} index={index} key={item.id} >
{(provided) => ( <Item provided={provided} item={item} isDragging={false} />)}
</Draggable>
)
);
}}
/>
)
);
}}
</Droppable>
</DragDropContext>
</div>
)
);
}
```
2 changes: 1 addition & 1 deletion docusaurus/sandpack/src/theme/CodeBlock/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ const RenderSandpack = (props) => {
: {}),
...(props['import'] === '@tanstack/react-table' ? { '@tanstack/react-table': 'latest' } : {}),
...(props['import'] === 'react-sortable-hoc' ? { 'react-sortable-hoc': '^1.11.0' } : {}),
...(props['import'] === 'react-beautiful-dnd' ? { 'react-beautiful-dnd': 'latest' } : {}),
...(props['import'] === 'react-beautiful-dnd' ? { '@hello-pangea/dnd': '16.3.0' } : {}),
...(props['import'] === '@emotion/styled' ? { '@emotion/styled': 'latest', '@emotion/react': 'latest' } : {}),
},
}}
Expand Down

0 comments on commit 12e53e5

Please sign in to comment.