Я использую список стилизованных компонентов для отображения некоторой информации.Я хочу, чтобы эта информация была сортируемой.Реальная проблема, которую я пытаюсь решить, на самом деле намного сложнее, чем я демонстрирую здесь.Поэтому любые странные варианты дизайна очень специфичны для того, что я пытаюсь сделать.Я просто упоминаю об этом, потому что код, который я показываю, будет очень упрощенным, но он также покажет некоторые из этих на первый взгляд странных вариантов дизайна.
Я читал эту статью: https://medium.com/the-andela-way/react-drag-and-drop-7411d14894b9
Темитоп Эммануэль (автор) сделал то, чего я пытаюсь достичь, но с простым делом.Я не знаю, проверял ли он все, что он предлагает в своей статье.
Выключен какой-то код:
import React, { Component, Fragment } from 'react';
import styled from 'styled-components';
export default class SomeList extends Component {
constructor(props) {
super(props);
// in real problem all of these are props
// pulled off the state of a parent
this.state = {
dragging: false,
listOfChildrenInOrder: ['1', '2', '3'],
itemComponent: styled.div`
border: 1px solid black;
`,
};
}
render() {
const {
dragging,
listOfChildrenInOrder,
itemComponent: ItemComponent,
} = this.state;
const {
children,
} = this.props;
const Container = styled.div`
display: grid;
grid-template-rows: max-content;
grid-template-columns: repeat(${listOfChildrenInOrder.length}, max-content) 1fr;
`;
const Droppable = styled.div`
&:hover {
background-color: rgba(0,0,0,0.4);
}
`;
return (
<Container>
<Fragment>
{listOfChildrenInOrder.map(((cid, i) => (
<ItemComponent
draggable
key={`ic-${cid}`}
style={{
gridArea: `1 / ${i + 1} / span 1 / span 1`,
}}
onDragStart={(e) => {
this.setState({ dragging: true });
e.dataTransfer.setData('text/plain', `${cid}`);
}}
onDragEnd={() => {
this.setState({ dragging: false });
// doesn't even fire anymore
}}
>
{children.find(c => c.key === cid)}
</ItemComponent>
)))}
</Fragment>
<Fragment>
{dragging && listOfChildrenInOrder.map(((cid, i) => (
<Droppable
key={`d-${cid}`}
style={{
gridArea: `1 / ${i + 1} / span 1 / span 1`,
}}
onDragOver={(e) => {
e.stopPropagation();
e.preventDefault();
}}
onDrop={() => {
// do whatever (out of scope), doesn't get called anyway
}}
>
{children.find(c => c.key === cid)}
</Droppable>
)))}
</Fragment>
</Container>
);
}
}
Я ожидаю, что реконсилятор (Fiber) обновит DOMузел без прямой замены его в середине операции перетаскивания.Я использую эти вещи в качестве маркеров.Реальная проблема, которую я пытаюсь решить, на самом деле влияет на то, куда именно отбрасываются вещи, поэтому сетка в реальной проблеме более тонкая, с большим количеством отбрасываемых объектов и одним компонентом элемента, охватывающим несколько столбцов сетки.Как я уже сказал: странный выбор, но не без цели.