Javascript 拖放虚拟列表和不同大小的项目
我正在尝试使用Javascript 拖放虚拟列表和不同大小的项目,javascript,reactjs,drag-and-drop,react-beautiful-dnd,Javascript,Reactjs,Drag And Drop,React Beautiful Dnd,我正在尝试使用react-beautiful-dnd和react-virtuoso(自动计算项目大小的虚拟列表)实现一个包含虚拟列表和不同大小项目的Trello react-virtuoso不是美丽的react-dnd示例的一部分,我面临两个问题: 拖动项目时无法滚动 我经常遇到这样的错误:不变式失败:只能为具有滚动容器的可拖放设备重新调用可拖放客户端 这里有一个 下拉列表.tsx import * as React from "react"; import { useState } fro
react-beautiful-dnd
和react-virtuoso
(自动计算项目大小的虚拟列表)实现一个包含虚拟列表和不同大小项目的Trello
react-virtuoso
不是美丽的react-dnd示例的一部分,我面临两个问题:
- 拖动项目时无法滚动
- 我经常遇到这样的错误:
不变式失败:只能为具有滚动容器的可拖放设备重新调用可拖放客户端
import * as React from "react";
import { useState } from "react";
import "./styles.css";
import { Virtuoso } from "react-virtuoso";
import {
Draggable,
DragDropContext,
Droppable,
DropResult,
ResponderProvided
} from "react-beautiful-dnd";
import { Item } from "./Item";
import { reorder } from "./App";
import { createItemList } from "./data";
import { ItemList, ItemType } from "./dtos";
const itemCount = 30;
export const VirtualDragDropList = () => {
const [itemList, setItemList] = useState<ItemList>(createItemList(itemCount));
const onDragEnd = (result: DropResult, provided: ResponderProvided) => {
// dropped outside the list
if (!result.destination) {
return;
}
const items = reorder(
itemList,
result.source.index,
result.destination.index
);
setItemList(items);
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable
droppableId="droppable"
mode="virtual"
renderClone={(provided, snapshot, rubric) => {
// console.log("provided", provided);
// console.log("snapshot", snapshot);
// console.log("rubric", rubric);
return (
<Item
itemData={itemList[(rubric as any).source.index]}
provided={provided}
index={(rubric as any).source.index} // typing seems wrong, hence the any.
/>
);
}}
>
{droppableProvided => (
<div ref={droppableProvided.innerRef}>
<Virtuoso
style={{ width: "300px", height: "400px" }}
totalCount={itemCount}
// item={index => <Item itemData={itemList[index]} />}
item={index => <Row itemData={itemList[index]} index={index} />}
/>
</div>
)}
</Droppable>
</DragDropContext>
);
};
const Row = React.memo((args: { itemData: ItemType; index: number }) => {
const { itemData, index } = args;
return (
<Draggable draggableId={itemData.id} index={index} key={itemData.id}>
{(provided, snapshot) => (
<Item itemData={itemData} index={index} provided={provided} />
)}
</Draggable>
);
});
import * as React from "react";
import { ItemType } from "./dtos";
export const Item: React.FC<{
index?: number;
itemData: ItemType | undefined;
provided?: any;
}> = props => {
const height = (props.itemData ? props.itemData.height : 10) * 3;
const style = {
margin: ".3rem",
padding: ".3rem",
display: "flex",
border: "1px solid lightgrey",
height: `${height}px`
};
return (
<div
ref={props.provided && props.provided.innerRef}
{...props.provided && props.provided.draggableProps}
{...props.provided && props.provided.dragHandleProps}
style={{ ...props.provided.draggableProps.style, ...style }}
>
{props.itemData && props.itemData.text}
</div>
);
};
import*as React from“React”;
从“react”导入{useState};
导入“/styles.css”;
从“react Virtuoso”导入{Virtuoso};
进口{
拖拉的,
DragDropContext,
可降落,
结果,
响应者提供
}从“反应美丽的dnd”;
从“/Item”导入{Item};
从“/App”导入{reorder};
从“/data”导入{createItemList};
从“/dtos”导入{ItemList,ItemType};
const itemCount=30;
导出常量VirtualDragDropList=()=>{
const[itemList,setItemList]=useState(createItemList(itemCount));
const onDragEnd=(结果:DropResult,提供:ResponderProvided)=>{
//被排除在名单之外
如果(!result.destination){
返回;
}
常量项=重新排序(
项目列表,
result.source.index,
result.destination.index
);
setItemList(项目);
};
返回(
{
//控制台日志(“已提供”,已提供);
//控制台日志(“快照”,快照);
//控制台日志(“rubric”,rubric);
返回(
);
}}
>
{droppableProvided=>(
}
item={index=>}
/>
)}
);
};
const Row=React.memo((参数:{itemData:ItemType;索引:number})=>{
常量{itemData,index}=args;
返回(
{(已提供,快照)=>(
)}
);
});
Item.tsx
import * as React from "react";
import { useState } from "react";
import "./styles.css";
import { Virtuoso } from "react-virtuoso";
import {
Draggable,
DragDropContext,
Droppable,
DropResult,
ResponderProvided
} from "react-beautiful-dnd";
import { Item } from "./Item";
import { reorder } from "./App";
import { createItemList } from "./data";
import { ItemList, ItemType } from "./dtos";
const itemCount = 30;
export const VirtualDragDropList = () => {
const [itemList, setItemList] = useState<ItemList>(createItemList(itemCount));
const onDragEnd = (result: DropResult, provided: ResponderProvided) => {
// dropped outside the list
if (!result.destination) {
return;
}
const items = reorder(
itemList,
result.source.index,
result.destination.index
);
setItemList(items);
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable
droppableId="droppable"
mode="virtual"
renderClone={(provided, snapshot, rubric) => {
// console.log("provided", provided);
// console.log("snapshot", snapshot);
// console.log("rubric", rubric);
return (
<Item
itemData={itemList[(rubric as any).source.index]}
provided={provided}
index={(rubric as any).source.index} // typing seems wrong, hence the any.
/>
);
}}
>
{droppableProvided => (
<div ref={droppableProvided.innerRef}>
<Virtuoso
style={{ width: "300px", height: "400px" }}
totalCount={itemCount}
// item={index => <Item itemData={itemList[index]} />}
item={index => <Row itemData={itemList[index]} index={index} />}
/>
</div>
)}
</Droppable>
</DragDropContext>
);
};
const Row = React.memo((args: { itemData: ItemType; index: number }) => {
const { itemData, index } = args;
return (
<Draggable draggableId={itemData.id} index={index} key={itemData.id}>
{(provided, snapshot) => (
<Item itemData={itemData} index={index} provided={provided} />
)}
</Draggable>
);
});
import * as React from "react";
import { ItemType } from "./dtos";
export const Item: React.FC<{
index?: number;
itemData: ItemType | undefined;
provided?: any;
}> = props => {
const height = (props.itemData ? props.itemData.height : 10) * 3;
const style = {
margin: ".3rem",
padding: ".3rem",
display: "flex",
border: "1px solid lightgrey",
height: `${height}px`
};
return (
<div
ref={props.provided && props.provided.innerRef}
{...props.provided && props.provided.draggableProps}
{...props.provided && props.provided.dragHandleProps}
style={{ ...props.provided.draggableProps.style, ...style }}
>
{props.itemData && props.itemData.text}
</div>
);
};
import*as React from“React”;
从“/dtos”导入{ItemType};
导出常量项:React.FC=props=>{
常量高度=(props.itemData?props.itemData.height:10)*3;
常量样式={
保证金:“.3rem”,
填充:“.3rem”,
显示:“flex”,
边框:“1px纯色浅灰色”,
高度:`${height}px`
};
返回(
{props.itemData&&props.itemData.text}
);
};
data.ts
import { ItemList } from "./dtos";
export const createItemList = (itemCount: number): ItemList => {
const itemList: ItemList = [];
for (let i = 0; i < itemCount; i++) {
itemList.push({
id: i.toString(),
text: `Item ${i}`,
height: Math.random() * 20
});
}
return itemList;
}
从“/dtos”导入{ItemList};
导出常量createItemList=(itemCount:number):ItemList=>{
常量itemList:itemList=[];
for(设i=0;i