3

Points to consider:

  • The example is made up but illustrates the problem.
  • In actual application global storage is used and action changing is being emitted inside hover() method of itemTarget. Here, to imitate global storage, window object is used.
  • Using ES7 decorators (or other ES7 syntax) is not allowed.

So, the problem is that in implementation below, when dragging, endDrag() method of itemSource is not being called.
Possible solutions would be create different (but practically the same) components which differ just by item types, import those components to the Container component and mount depending on props.itemType – so, it's not an DRY option.

The questions are: 1. How to do it right? How to reuse and render a draggable component which have depended on Container's props itemType inside DragSource/DropTarget? 2. Why does the solution below not work? Why is the endDrag() method not being called?

Container.js:

import React, { Component } from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

import Item from './Item';
import ItemDndDecorator from './ItemDndDecorator';

const style = {
  width: 333,
};

class Container extends Component {
  state = {some: true}

  hoverHandle = () => {
    this.setState({some: !this.state.some})
  }

  render() {
    const Item1 = ItemDndDecorator(Item, 'item1')
    const Item2 = ItemDndDecorator(Item, 'item2')

    window.hoverHandle = this.hoverHandle

    return (
      <div style={style}>
        <Item1>
          <Item2>
            some text 1
          </Item2>
        </Item1>
      </div>
    );
  }
}

export default DragDropContext(HTML5Backend)(Container)

Item.js:

import React from 'react';

const style = {
  border: '1px dashed gray',
  padding: '1rem',
  margin: '1rem',
  cursor: 'move',
};

function Item(props) {
  const { connectDragSource, connectDropTarget } = props;

  return connectDragSource(connectDropTarget(
    <div style={style}>
      {props.children}
    </div>,
  ));
}

export default Item

ItemDnDDecorator.js:

import { DragSource, DropTarget } from 'react-dnd';

const itemSource = {
  beginDrag(props) {
    console.log('begin drag');
    return { id: props.id } ;
  },
  endDrag() {
    console.log('end drag');
  }
};

const itemTarget = {
  hover() {
    window.hoverHandle()
  }
};

function ItemDndDecorator(component, itemType) {
  return (
    DropTarget(itemType, itemTarget, connect => ({
      connectDropTarget: connect.dropTarget(),
    }))(
      DragSource(itemType, itemSource, (connect, monitor) => ({
        connectDragSource: connect.dragSource(),
        isDragging: monitor.isDragging(),
      }))(component))
  )
}

export default ItemDndDecorator
olegzhermal
  • 799
  • 10
  • 26

0 Answers0