React DnD 拖动时显示整个列表

Yan*_*hon 5 meteor reactjs material-ui react-dnd

我正在尝试使用Material UI集成React DnD,并且在拖动时,整个列表显示为拖动的元素。我已尽我所能理解这些示例,这就是我所拥有的ListListItem

import React, { Component, PropTypes } from 'react';
import { Random } from 'meteor/random';
import LocalizedComponent from '/client/components/LocalizedComponent';
// MUI
import { List, ListItem } from 'material-ui/List';
// ---
import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
import { findDOMNode } from 'react-dom';

import HTML5Backend from 'react-dnd-html5-backend';


const itemSource = {
  beginDrag(props) {
    return {
      id: props.id,
      index: props.index
    };
  },
};

const itemTarget = {
  hover(props, monitor, component) {
    const dragIndex = monitor.getItem().index;
    const hoverIndex = props.index;

    // Don't replace items with themselves
    if (dragIndex === hoverIndex) {
      return;
    }

    // Determine rectangle on screen
    const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();

    // Get vertical middle
    const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

    // Determine mouse position
    const clientOffset = monitor.getClientOffset();

    // Get pixels to the top
    const hoverClientY = clientOffset.y - hoverBoundingRect.top;

    // Only perform the move when the mouse has crossed half of the items height
    // When dragging downwards, only move when the cursor is below 50%
    // When dragging upwards, only move when the cursor is above 50%

    // Dragging downwards
    if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
      return;
    }

    // Dragging upwards
    if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
      return;
    }

    // Time to actually perform the action
    props.onMoveItem(dragIndex, hoverIndex);

    // Note: we're mutating the monitor item here!
    // Generally it's better to avoid mutations,
    // but it's good here for the sake of performance
    // to avoid expensive index searches.
    monitor.getItem().index = hoverIndex;
  },
};


class SortableListComponent extends Component {

  render() {
    const { children, onMoveItem } = this.props;
    let index = 0;

    return (
      <List>
        { React.Children.map(children, child => React.cloneElement(child, {
          id: Random.id(),
          index: index++,
          onMoveItem: onMoveItem
        })) }
      </List>
    );
  }
}

SortableListComponent.propTypes = {
  onMoveItem: PropTypes.func.isRequired
};


class SortableListItemComponent extends Component {

  render() {
    const {
      id,
      index,
      isDragging,
      connectDragSource,
      connectDropTarget,
      onMoveItem,
      ...other
    } = this.props;
    const opacity = 1; // isDragging ? 0 : 1;

    return connectDragSource(connectDropTarget(
      <div style={{ opacity }}>
        <ListItem { ...other } disabled={ isDragging } />
      </div>
    ));
  }
}
SortableListItemComponent.propTypes = {
  connectDragSource: PropTypes.func.isRequired,
  connectDropTarget: PropTypes.func.isRequired,
  id: PropTypes.any.isRequired,
  index: PropTypes.number.isRequired,
  isDragging: PropTypes.bool.isRequired,
  onMoveItem: PropTypes.func.isRequired,
};


export const SortableList = DragDropContext(HTML5Backend)(SortableListComponent);

export const SortableListItem = DropTarget('SortableListItem', itemTarget, connect => ({
  connectDropTarget: connect.dropTarget(),
}))(DragSource('SortableListItem', itemSource, (connect, monitor) => ({
  connectDragSource: connect.dragSource(),
  isDragging: monitor.isDragging(),
}))(SortableListItemComponent));
Run Code Online (Sandbox Code Playgroud)

基本上,我替换了ListSortableListListItemSortableListItem就是我在拖动时看到的

在此输入图像描述

我究竟做错了什么?

编辑

例如,这是一个示例用法

<SortableList>
  { actions.map((action, index) => (
    <SortableListItem id={ action.name } key={ index }
      primaryText={ (index + 1) + '. ' + action.name }
      onTouchTap={ this.handleActionEdit.bind(this, index) }
    />
  )) }
</SortableList>
Run Code Online (Sandbox Code Playgroud)

或者

<SortableList>
  { actions.map((action, index) => (
    <SortableListItem id={ action.name } key={ action.name }
      primaryText={ (index + 1) + '. ' + action.name }
      onTouchTap={ this.handleActionEdit.bind(this, index) }
    />
  )) }
</SortableList>
Run Code Online (Sandbox Code Playgroud)

ETC。

它不会改变任何事情。

Sho*_*ota 1

问题可能在于您如何将id和传递key到您的子组件中。使用 React dnd生成随机数id最终会出现问题。您应该做的是,根据您的情况,您应该将每个单独项目的唯一 ID 添加到您的数据中children。一个例子在这里:https://github.com/react-dnd/react-dnd/blob/master/examples/04%20Sortable/Simple/Container.js#L17

{ React.Children.map(children, child => React.cloneElement(child, {
    id: child.id,
    key: child.id,
    index: index++,
    onMoveItem: onMoveItem
})) }
Run Code Online (Sandbox Code Playgroud)