React
Alugard-Drop works seamlessly with React. As with any DOM manipulation library in React, the key is to initialize the library after the component has mounted and the DOM elements are available. We use the useEffect and useRef hooks for this.
Example
This is a functional React component demonstrating a basic drag-and-drop setup between two lists.
tsx
import React, { useEffect, useRef, useState } from 'react';
import alugard from 'alugard-drop';
import 'alugard-drop/style.css';
export default function DragDropExample() {
const leftContainerRef = useRef<HTMLDivElement>(null);
const rightContainerRef = useRef<HTMLDivElement>(null);
const drakeRef = useRef<any>(null);
const [leftItems, setLeftItems] = useState(['Item 1', 'Item 2', 'Item 3']);
const [rightItems, setRightItems] = useState(['Item 4', 'Item 5', 'Item 6']);
useEffect(() => {
// Only initialize if the containers are ready
if (leftContainerRef.current && rightContainerRef.current) {
// Initialize Alugard-Drop with the container elements
drakeRef.current = alugard([leftContainerRef.current, rightContainerRef.current]);
// Optional: Listen for the 'drop' event
drakeRef.current.on('drop', (el: HTMLElement, target: HTMLElement, source: HTMLElement, sibling: HTMLElement | null) => {
console.log(`Successfully dropped an item into ${target.id}`);
// Note: For complex state sync, you would update your React state here
// based on the DOM changes made by Alugard-Drop.
});
}
// Cleanup: destroy the drake instance when component unmounts
return () => {
if (drakeRef.current) {
drakeRef.current.destroy();
}
};
}, []); // Run once on mount
return (
<div style={{ display: 'flex', gap: '20px' }}>
<div
id="left-list"
ref={leftContainerRef}
style={{ width: '250px', minHeight: '300px', background: '#f4f4f5', padding: '10px', borderRadius: '8px' }}
>
<h3>List A</h3>
{leftItems.map((item, index) => (
<div key={`left-${index}`} className="draggable-item" style={{ padding: '15px', background: 'white', border: '1px solid #e4e4e7', marginBottom: '10px', cursor: 'grab', borderRadius: '4px' }}>
{item}
</div>
))}
</div>
<div
id="right-list"
ref={rightContainerRef}
style={{ width: '250px', minHeight: '300px', background: '#f4f4f5', padding: '10px', borderRadius: '8px' }}
>
<h3>List B</h3>
{rightItems.map((item, index) => (
<div key={`right-${index}`} className="draggable-item" style={{ padding: '15px', background: 'white', border: '1px solid #e4e4e7', marginBottom: '10px', cursor: 'grab', borderRadius: '4px' }}>
{item}
</div>
))}
</div>
</div>
);
}Key Takeaways for React
- DOM Refs: Use
useRefto get the DOM node of your container elements. Alugard-Drop needs raw DOM elements, not React components. - Initialization: Always initialize
alugard()insideuseEffect(orcomponentDidMountfor class components) so the DOM is guaranteed to be present. - Cleanup: Return a cleanup function from your
useEffectto calldrake.destroy()to prevent memory leaks if the component unmounts. - State Synchronization: Alugard-Drop updates the actual DOM directly. If your UI relies heavily on React state (
leftItemsandrightItems), you need to listen for thedropevent and manually update your state arrays to reflect the new DOM order, so React doesn't override the changes on the next render.
