Вызов setState в onDragStart вызывает удаление узла DOM? - PullRequest
0 голосов
/ 19 июня 2019

Я использую список стилизованных компонентов для отображения некоторой информации.Я хочу, чтобы эта информация была сортируемой.Реальная проблема, которую я пытаюсь решить, на самом деле намного сложнее, чем я демонстрирую здесь.Поэтому любые странные варианты дизайна очень специфичны для того, что я пытаюсь сделать.Я просто упоминаю об этом, потому что код, который я показываю, будет очень упрощенным, но он также покажет некоторые из этих на первый взгляд странных вариантов дизайна.

Я читал эту статью: 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узел без прямой замены его в середине операции перетаскивания.Я использую эти вещи в качестве маркеров.Реальная проблема, которую я пытаюсь решить, на самом деле влияет на то, куда именно отбрасываются вещи, поэтому сетка в реальной проблеме более тонкая, с большим количеством отбрасываемых объектов и одним компонентом элемента, охватывающим несколько столбцов сетки.Как я уже сказал: странный выбор, но не без цели.

1 Ответ

0 голосов
/ 20 июня 2019

Хорошо, теперь я знаю, что привело к сбою всей этой операции. Причиной было динамическое создание новых стилизованных компонентов в цикле рендеринга. Никогда не делай этого. Просто усвоил еще одно практическое правило.

...