Javascript React DND-无法在拖放事件后将新项添加到状态
在将此代码实现到图像上传程序之前,我正在开发一个简单版本的ReactDND 每次添加图像时,它都会被添加到状态并传递到ReactDND,这样它就可以拖动,也可以拖放(这样用户就可以重新排列他们的图像) 一切都很好,除了一件事。我遇到的问题是在添加多个图像后,一旦我拖放图像(工作),ReactDND的状态不再更新,我无法添加新图像 下面是我的代码(注意,我只是使用一个按钮向状态添加额外的项): 主要组成部分:Javascript React DND-无法在拖放事件后将新项添加到状态,javascript,reactjs,drag-and-drop,react-dnd,Javascript,Reactjs,Drag And Drop,React Dnd,在将此代码实现到图像上传程序之前,我正在开发一个简单版本的ReactDND 每次添加图像时,它都会被添加到状态并传递到ReactDND,这样它就可以拖动,也可以拖放(这样用户就可以重新排列他们的图像) 一切都很好,除了一件事。我遇到的问题是在添加多个图像后,一旦我拖放图像(工作),ReactDND的状态不再更新,我无法添加新图像 下面是我的代码(注意,我只是使用一个按钮向状态添加额外的项): 主要组成部分: import React from 'react'; // Drag and drop
import React from 'react';
// Drag and drop stuff
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Container from './Container';
class ImageUploader extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [],
listCount: 1
};
this.onAddItem = this.onAddItem.bind(this);
}
onAddItem(e) {
e.preventDefault();
var listArray = this.state.list;
var buildObject = {
text: 'Jeremy' + this.state.listCount.toString(),
age: '25',
id: this.state.listCount
};
listArray.push(buildObject);
let newListCount = this.state.listCount + 1;
this.setState({
list: listArray,
listCount: newListCount
});
console.log(this.state.list);
}
render() {
return (
<div>
<h1>Add to List</h1>
<button onClick={this.onAddItem}>Add Item</button>
<h1>The List</h1>
<Container id={1} list={this.state.list} />
</div>
)
}
}
export default DragDropContext(HTML5Backend)(ImageUploader);
从“React”导入React;
//拖放东西
从'react dnd'导入{DragDropContext};
从“react-dnd-html5-backend”导入html5后端;
从“./Container”导入容器;
类ImageUploader扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
名单:[],
列表计数:1
};
this.onAddItem=this.onAddItem.bind(this);
}
附加项(e){
e、 预防默认值();
var listary=this.state.list;
var buildObject={
文本:“Jeremy”+this.state.listCount.toString(),
年龄:"25",,
id:this.state.listCount
};
push(buildObject);
让newListCount=this.state.listCount+1;
这是我的国家({
列表:listArray,
listCount:newListCount
});
log(this.state.list);
}
render(){
返回(
添加到列表中
添加项
名单
)
}
}
导出默认DragDropContext(HTML5后端)(ImageUploader);
容器:
import React, { Component } from 'react';
import update from 'react/lib/update';
import Card from './Card';
import { DropTarget } from 'react-dnd';
class Container extends Component {
constructor(props) {
super(props);
this.state = { cards: props.list };
}
pushCard(card) {
this.setState(update(this.state, {
cards: {
$push: [ card ]
}
}));
}
removeCard(index) {
this.setState(update(this.state, {
cards: {
$splice: [
[index, 1]
]
}
}));
}
moveCard(dragIndex, hoverIndex) {
const { cards } = this.state;
const dragCard = cards[dragIndex];
this.setState(update(this.state, {
cards: {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragCard]
]
}
}));
}
render() {
const { cards } = this.state;
const { canDrop, isOver, connectDropTarget } = this.props;
const isActive = canDrop && isOver;
const style = {
width: "200px",
height: "404px",
border: '1px dashed gray'
};
const backgroundColor = isActive ? 'lightgreen' : '#FFF';
return connectDropTarget(
<div className="houzes-dropbox">
{cards.map((card, i) => {
return (
<Card
key={card.id}
index={i}
listId={this.props.id}
card={card}
removeCard={this.removeCard.bind(this)}
moveCard={this.moveCard.bind(this)} />
);
})}
</div>
);
}
}
const cardTarget = {
drop(props, monitor, component ) {
const { id } = props;
const sourceObj = monitor.getItem();
if ( id !== sourceObj.listId ) component.pushCard(sourceObj.card);
return {
listId: id
};
}
}
export default DropTarget("CARD", cardTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
}))(Container);
import React,{Component}来自'React';
从“react/lib/update”导入更新;
从“./卡”导入卡;
从'react dnd'导入{DropTarget};
类容器扩展组件{
建造师(道具){
超级(道具);
this.state={cards:props.list};
}
扑克牌{
this.setState(更新)(this.state{
卡片:{
$push:[卡]
}
}));
}
移除卡片(索引){
this.setState(更新)(this.state{
卡片:{
$splice:[
[索引,1]
]
}
}));
}
moveCard(dragIndex、hoverIndex){
const{cards}=this.state;
常量绘图卡=卡片[绘图索引];
this.setState(更新)(this.state{
卡片:{
$splice:[
[dragIndex,1],
[悬停索引,0,dragCard]
]
}
}));
}
render(){
const{cards}=this.state;
const{canDrop,isOver,connectDropTarget}=this.props;
const isActive=canDrop&&isOver;
常量样式={
宽度:“200px”,
高度:“404px”,
边框:“1px灰色虚线”
};
const backgroundColor=isActive?'lightgreen':'#FFF';
返回connectDropTarget(
{cards.map((card,i)=>{
返回(
);
})}
);
}
}
常数cardTarget={
下降(道具、监视器、组件){
const{id}=props;
const sourceObj=monitor.getItem();
if(id!==sourceObj.listId)component.pushCard(sourceObj.card);
返回{
listId:id
};
}
}
导出默认DropTarget(“卡”,cardTarget,(连接,监视)=>({
connectDropTarget:connect.dropTarget(),
isOver:monitor.isOver(),
canDrop:monitor.canDrop()
}))(集装箱);
卡片:
import React,{Component}来自'React';
从'react dom'导入{findDOMNode};
从'react dnd'导入{DragSource,DropTarget};
从“lodash/flow”导入流量;
常量样式={
边框:“1px灰色虚线”,
填充:“0.5rem 1rem”,
保证金:'.5rem',
背景颜色:“白色”,
光标:“移动”
};
类卡扩展组件{
render(){
const{card,isDraging,connectDragSource,connectDropTarget}=this.props;
常数不透明度=IsDraging?0:1;
//背景URL
让backgroundUrl={
背景图片:“url(“+”http://localhost:4000/uploads/2017/8/a3ff91dc-2f80-42f7-951a-e9a74bf954d7-1200x800.jpeg“+”“
};
控制台日志(卡片);
返回connectDragSource(connectDropTarget(
{card.text}
{card.age}
));
}
}
常数cardSource={
开端(道具){
返回{
索引:props.index,
listId:props.listId,
卡片:道具
};
},
endDrag(道具、监视器){
const item=monitor.getItem();
const dropResult=monitor.getDropResult();
if(dropResult&&dropResult.listId!==item.listId){
道具移除卡(项目索引);
}
}
};
常数cardTarget={
悬停(道具、监视器、组件){
const dragIndex=monitor.getItem().index;
常数hoverIndex=props.index;
const sourceListId=monitor.getItem().listId;
//不要用物品本身替换物品
if(dragIndex==悬停索引){
回来
}
//确定屏幕上的矩形
const hoverBoundingRect=findDOMNode(component.getBoundingClientRect();
//垂直居中
const hovermiddle=(hoverBoundingRect.bottom-hoverBoundingRect.top)/2;
//确定鼠标位置
const clientOffset=monitor.getClientOffset();
//将像素置于顶部
const hoverClientY=clientOffset.y-hoverBoundingRec
import React, { Component } from 'react';
import { findDOMNode } from 'react-dom';
import { DragSource, DropTarget } from 'react-dnd';
import flow from 'lodash/flow';
const style = {
border: '1px dashed grey',
padding: '0.5rem 1rem',
margin: '.5rem',
backgroundColor: 'white',
cursor: 'move'
};
class Card extends Component {
render() {
const { card, isDragging, connectDragSource, connectDropTarget } = this.props;
const opacity = isDragging ? 0 : 1;
// Background URL
let backgroundUrl = {
backgroundImage: "url(" + "http://localhost:4000/uploads/2017/8/a3ff91dc-2f80-42f7-951a-e9a74bf954d7-1200x800.jpeg" + ")"
};
console.log(card);
return connectDragSource(connectDropTarget(
<div className={`uploadedImageWrapper col-md-6 col-sm-12`}>
<div className="uploadedImage">
<span style={backgroundUrl} />
{card.text}
{card.age}
</div>
</div>
));
}
}
const cardSource = {
beginDrag(props) {
return {
index: props.index,
listId: props.listId,
card: props.card
};
},
endDrag(props, monitor) {
const item = monitor.getItem();
const dropResult = monitor.getDropResult();
if ( dropResult && dropResult.listId !== item.listId ) {
props.removeCard(item.index);
}
}
};
const cardTarget = {
hover(props, monitor, component) {
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
const sourceListId = monitor.getItem().listId;
// 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
if ( props.listId === sourceListId ) {
props.moveCard(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;
}
}
};
export default flow(
DropTarget("CARD", cardTarget, connect => ({
connectDropTarget: connect.dropTarget()
})),
DragSource("CARD", cardSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging()
}))
)(Card);
import React from 'react';
// Drag and drop stuff
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Container from './Container';
class ImageUploader extends React.Component {
constructor(props) {
super(props);
this.state = {
list: [],
listCount: 1
};
this.onAddItem = this
.onAddItem
.bind(this);
this.listChanged = this.listChanged.bind(this);
}
onAddItem(e) {
e.preventDefault();
var listArray = this.state.list;
var buildObject = {
text: 'Jeremy' + this
.state
.listCount
.toString(),
age: '25',
id: this.state.listCount
};
listArray.push(buildObject);
let newListCount = this.state.listCount + 1;
this.setState({list: listArray, listCount: newListCount});
}
listChanged(newList) {
this.setState({
list: newList
})
}
render() {
return (
<div>
<h1>Add to List</h1>
<button onClick={this.onAddItem}>Add Item</button>
<h1>The List</h1>
<Container id={1} list={this.state.list} listChanged={this.listChanged}/>
</div>
)
}
}
export default DragDropContext(HTML5Backend)(ImageUploader);
import React, { Component } from 'react';
import update from 'react/lib/update';
import Card from './Card';
import { DropTarget } from 'react-dnd';
class Container extends Component {
constructor(props) {
super(props);
this.state = { cards: this.props.list };
}
pushCard(card) {
this.setState(update(this.state, {
cards: {
$push: [ card ]
}
}));
}
removeCard(index) {
this.setState(update(this.state, {
cards: {
$splice: [
[index, 1]
]
}
}));
}
moveCard(dragIndex, hoverIndex) {
const { cards } = this.state;
const dragCard = cards[dragIndex];
this.setState(update(this.state, {
cards: {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragCard]
]
}
}));
}
componentWillReceiveProps(nextProps) {
// You don't have to do this check first, but it can help prevent an unneeded render
if (nextProps.list !== this.state.cards) {
this.props.listChanged(this.state.cards);
}
}
render() {
const { cards } = this.state;
const { canDrop, isOver, connectDropTarget } = this.props;
const isActive = canDrop && isOver;
const style = {
width: "200px",
height: "404px",
border: '1px dashed gray'
};
const backgroundColor = isActive ? 'lightgreen' : '#FFF';
return connectDropTarget(
<div className="houzes-dropbox">
{cards.map((card, i) => {
return (
<Card
key={card.id}
index={i}
listId={this.props.id}
card={card}
removeCard={this.removeCard.bind(this)}
moveCard={this.moveCard.bind(this)} />
);
})}
</div>
);
}
}
const cardTarget = {
drop(props, monitor, component ) {
const { id } = props;
const sourceObj = monitor.getItem();
if ( id !== sourceObj.listId ) component.pushCard(sourceObj.card);
return {
listId: id
};
}
}
export default DropTarget("CARD", cardTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop()
}))(Container);