Пользовательский интерфейс мерцает, когда я перетаскиваю элемент и перетаскиваю его

У меня проблема с тем, чтобы response-beautiful-dnd работал без мерцания. Я последовал примеру из курса «Умник». Вот мой образец кода.

Контейнер списка предметов

  onDragEnd = (result) => {
    if (this.droppedOutsideList(result) || this.droppedOnSamePosition(result)) {
      return;
    }
    this.props.itemStore.reorderItem(result);
  }

  droppedOnSamePosition = ({ destination, source }) => destination.droppableId
    === source.droppableId && destination.index === source.index;

  droppedOutsideList = result => !result.destination;

  render() {
    return (
      <DragDropContext onDragEnd={this.onDragEnd}>
        <div>
          {this.props.categories.map((category, index) => (
            <ListCategory
              key={index}
              category={category}
              droppableId={category._id}
            />
          ))}
        </div>
      </DragDropContext>
    );
  }

Категория товара

const ListCategory = ({
  category, droppableId,
}) => (
  <Droppable droppableId={String(droppableId)}>
    {provided => (
      <div
        {...provided.droppableProps}
        ref={provided.innerRef}
      >
        <ListTitle
          title={category.name}
        />
        <ListItems category={category} show={category.items && showIndexes} />
        {provided.placeholder}
      </div>
    )}
  </Droppable>
);

Список пунктов

   <Fragment>
      {category.items.map((item, index) => (
        <ListItem
          key={index}
          item={item}
          index={index}
        />
      ))}
    </Fragment>

Предметы

  render() {
    const {
      item, index, categoryIndex, itemStore,
    } = this.props;

    return (
      <Draggable key={index} draggableId={item._id} index={index}>
        {(provided, snapshot) => (
          <div
            role="presentation"
            className={cx({
              'list-item-container': true,
              'selected-list-item': this.isSelectedListItem(item._id),
            })}
            ref={provided.innerRef}
            {...provided.draggableProps}
            {...provided.dragHandleProps}
            style={getItemStyle(snapshot.isDragging, provided.draggableProps.style)}
            onClick={this.handleItemClick}
          >
            <div className={cx('select-title')}>
             <p className={cx('list-item-name')}>{item.title}</p>
            </div>
                {capitalize(item.importance)}
            </div>
          </div>
        )}
      </Draggable>
    );
  }

Способ изменения порядка элементов (я использую Mobx-State_Tree)

    reorderItem: flow(function* reorderItem(result) {
      const { source, destination } = result;

      const categorySnapshot = getSnapshot(self.itemCategories);
      const sourceCatIndex = self.itemCategories
        .findIndex(category => category._id === source.droppableId);
      const destinationCatIndex = self.itemCategories
        .findIndex(category => category._id === destination.droppableId);
      const sourceCatItems = Array.from(categorySnapshot[sourceCatIndex].items);
      const [draggedItem] = sourceCatItems.splice(source.index, 1);

      if (sourceCatIndex === destinationCatIndex) {
        sourceCatItems.splice(destination.index, 0, draggedItem);
        const prioritizedItems = setItemPriorities(sourceCatItems);
        applySnapshot(self.itemCategories[sourceCatIndex].items, prioritizedItems);
        try {
          yield itemService.bulkEditPriorities(prioritizedItems);
        } catch (error) {
          console.error(`Problem editing priorities: ${error}`);
        }
      } else {
        const destinationCatItems = Array.from(categorySnapshot[destinationCatIndex].items);
        destinationCatItems.splice(destination.index, 0, draggedItem);

        const prioritizedSourceItems = setItemPriorities(sourceCatItems);
        applySnapshot(self.itemCategories[sourceCatIndex].items, prioritizedSourceItems);

        const prioritizedDestItems = setItemPriorities(destinationCatItems);
        applySnapshot(self.itemCategories[destinationCatIndex].items, prioritizedDestItems);
        try {
          const sourceCatId = categorySnapshot[sourceCatIndex]._id;
          const originalItemId = categorySnapshot[sourceCatIndex].items[source.index]._id;
          yield itemService.moveItemToNewCategory(originalItemId, sourceCatId, destinationCatIndex);
        } catch (error) {
          console.error(`Problem editing priorities: ${error}`);
        }
      }
    }),

Образец данных

const itemData = [
    {
      _id: 'category-1',
      title: 'Backlog',
      items: [
        { _id: 'item-1', title: 'Here and back again' },
    },
    {
      _id: 'category-2',
      title: 'In progress',
      items: []
    },
   {
      _id: 'category-3',
      title: 'Done',
      items: []
    }
  }
}
Summary

Когда элемент и перетаскивается, я проверяю, упал ли элемент вне контекста dnd или в том же положении, из которого он был перетащен. Если это правда, я ничего не делаю. Если элемент удаляется в контексте, я проверяю, был ли он удален в той же категории. если true, я удаляю элемент из его текущей позиции, помещаю его в целевую позицию, обновляю свое состояние и выполняю вызов API.

Если он был удален в другую категорию, я удаляю элемент из исходной категории, добавляю в новую категорию, обновляю состояние и выполняю вызов API. Я что-то упускаю?


person Chukwuma Ezumezu    schedule 01.07.2019    source источник


Ответы (1)


Я использую как mst, так и библиотеку react-beautiful-dnd, я просто вставлю свой метод действия onDragEnd

onDragEnd(result: DropResult) {
  const { source, destination } = result;

  // dropped outside the list
  if (!destination) {
    return;
  }

  if (source.droppableId === destination.droppableId) {
    (self as any).reorder(source.index, destination.index);
  }
},
reorder(source: number, destination: number) {
  const tempLayout = [...self.layout];
  const toMove = tempLayout.splice(source, 1);
  const item = toMove.pop();

  tempLayout.splice(destination + lockedCount, 0, item);

  self.layout = cast(tempLayout);
},

Думаю, чтобы избежать мерцания, нужно избегать использования applySnapshot

Вы можете заменить эту логику

      const sourceCatItems = Array.from(categorySnapshot[sourceCatIndex].items);
      const [draggedItem] = sourceCatItems.splice(source.index, 1);

      sourceCatItems.splice(destination.index, 0, draggedItem);
      const prioritizedItems = setItemPriorities(sourceCatItems);
      applySnapshot(self.itemCategories[sourceCatIndex].items, prioritizedItems);

просто splice items дерево

const [draggedItem] = categorySnapshot[sourceCatIndex].items.splice(destination.index, 0, draggedItem)

таким образом вам не нужно applySnapshot на исходных элементах после

person etudor    schedule 13.09.2019