考慮すべき点:
- この例はでっち上げですが、問題を示しています。
- 実際のアプリケーションではグローバル ストレージが使用され、アクション変更は 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