3

考慮すべき点:

  • この例はでっち上げですが、問題を示しています。
  • 実際のアプリケーションではグローバル ストレージが使用され、アクション変更は itemTarget の hover() メソッド内で発行されています。ここでは、グローバル ストレージを模倣するために、window オブジェクトが使用されます。
  • ES7 デコレータ (または他の ES7 構文) の使用は許可されていません。

というわけで、以下の実装では、ドラッグ時に itemSource の endDrag() メソッドが呼び出されていないのが問題です。
考えられる解決策は、アイテム タイプだけが異なる異なる (ただし実際には同じ) コンポーネントを作成し、それらのコンポーネントを Container コンポーネントにインポートして、props.itemType に応じてマウントすることです。つまり、DRY オプションではありません。

質問は次のとおりです。 1. それを正しく行う方法は? DragSource/DropTarget 内のコンテナの props itemType に依存しているドラッグ可能なコンポーネントを再利用してレンダリングする方法は? 2. 以下の解決策が機能しないのはなぜですか? endDrag() メソッドが呼び出されないのはなぜですか?

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)

アイテム.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
4

0 に答える 0