Firstly, Thank you for looking at my problem. I am trying to implement and learn the logic of dnd-kit in react, & I have created this webapp where the elements that are being mapped into a SortableContext are react components. As Shown in the image below, all three elements are showing up and if drag is performed, it is giving the active & over data, But I can't seem to apply any Transform and Translate CSS into it.
I have tried to console log the transform and translate and it shows null & Undefined respectively. Here is the code for the main App.js,
import 'bootstrap/dist/css/bootstrap.min.css';
import Container from 'react-bootstrap/Container';
import {
DndContext,
closestCenter
} from "@dnd-kit/core";
import {
SortableContext,
arrayMove,
verticalListSortingStrategy
} from '@dnd-kit/sortable';
import { SortableItem } from './sortableItem';
import {useState} from 'react';
import NewTextBlock from './NewTextBlock';
import TextBlock from './TextBlock';
import NewBlock from './NewBlock';
function App() {
const [elements, setElements] = useState([
{
name : "Block1",
element : <NewTextBlock />
},
{
name : "Block2",
element : <TextBlock />
},
{
name : "Block3",
element : <NewBlock />
}]);
return (
<DndContext
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
>
<Container className='p-3' style={{width : "50%"}} align="center">
<h3>Lol what</h3>
<SortableContext
items={elements}
strategy={verticalListSortingStrategy}
>
{elements.map((block) => {
return(
<SortableItem key={block.name} id={block.name}>
{block.element}
</SortableItem>
)
})}
</SortableContext>
</Container>
</DndContext>
);
function handleDragEnd(e){
const {active, over} = e;
console.log("active : " + active.id);
console.log("over : " + over.id);
if(active.id !== over.id){
setElements((items) => {
const activeIndex = items.indexOf(active.id);
const overIndex = items.indexOf(over.id);
return arrayMove(items, activeIndex, overIndex);
})
}
}
}
export default App;
And The code for the Sortable Item,
import { CSS } from "@dnd-kit/utilities";
export function SortableItem(props) {
const { attributes, listeners, setNodeRef, transform, transition } =
useSortable({ id: props.id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
cursor: "grabbing",
backgroundColor: "white",
border: "1px solid black",
boxShadow: "1px 1px 2px grey",
};
return (
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
{props.children}
</div>
);
}
The Element Blocks have nothing but Card components by bootstrap.
You didn't add sensors to DndContext read here
Have to import them from @dnd-kit/core and add them as a prop of DndContext.
The one I have written bellow are best (in my experience), because they work best on mobile. You can use just PointerSensor with KeyboardSensor. You can find more details about the differences in doc.
import {
DndContext,
DragEndEvent,
KeyboardSensor,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
function App() {
// here are dafined
const sensors = useSensors(
useSensor(MouseSensor, {
activationConstraint: {
distance: 8,
},
}),
useSensor(TouchSensor, {
activationConstraint: {
delay: 200,
tolerance: 6,
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
}),
);
const [elements, setElements] = useState([
{
name : "Block1",
element : <NewTextBlock />
},
{
name : "Block2",
element : <TextBlock />
},
{
name : "Block3",
element : <NewBlock />
}]);
return (
<DndContext
// here must add them
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
>
<Container className='p-3' style={{width : "50%"}} align="center">
<h3>Lol what</h3>
<SortableContext
items={elements}
strategy={verticalListSortingStrategy}
>
{elements.map((block) => {
return(
<SortableItem key={block.name} id={block.name}>
{block.element}
</SortableItem>
)
})}
</SortableContext>
</Container>
</DndContext>
);
Let me know if it worked.
Tip: if you need those css class work only when item is dragging you should use isDragging prop of useSortable and make if statement to add this css then isDragging is true.
const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
useSortable({ id: props.id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
// for example like this
cursor: isDragging ? "grabbing" : "pointer",
backgroundColor: "white",
border: "1px solid black",
boxShadow: "1px 1px 2px grey",
};