需要考虑的要点:
- 这个例子是虚构的,但说明了问题。
- 在实际应用程序中使用全局存储,并且在 itemTarget 的 hover() 方法中发出动作更改。这里,为了模拟全局存储,使用了 window 对象。
- 不允许使用 ES7 装饰器(或其他 ES7 语法)。
所以,问题是在下面的实现中,当拖动时,没有调用 itemSource 的 endDrag() 方法。
可能的解决方案是创建不同(但实际上相同)的组件,这些组件仅因项目类型而异,将这些组件导入到 Container 组件并根据 props.itemType 进行挂载——因此,它不是 DRY 选项。
问题是: 1. 怎么做才对?如何在 DragSource/DropTarget 中重用和渲染依赖于 Container 的 props itemType 的可拖动组件?2. 为什么下面的解决方案不起作用?为什么没有调用 endDrag() 方法?
容器.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