2016-11-10 38 views
1

我正在构建一个应用程序,需要对一个项目表进行排序,并根据排序顺序更改它们的orderNumber。我安装并使用了一个名为react-dnd的库来处理排序/排序的功能,并且迄今为止它的工作很好。即时通讯的问题是更新。当用户移动其中一个项目时,我需要向api发送一个PUT请求并更新它的orderNumber。昨天晚上工作很好,这是我的代码。React Drag n在道具之后拖放PUT请求

的列表项(项目正在被排序,并更新):

import React, {PropTypes} from 'react'; 
import {Link} from 'react-router'; 
import {DragSource, DropTarget} from 'react-dnd'; 
import sdk from '../../js/sdk'; 
import ItemTypes from './ItemTypes'; 

const itemSource = { 
    beginDrag(props) { 
     return {id: props.id}; 
    } 
}; 

const itemTarget = { 
    hover(props, monitor) { 
     const draggedId = monitor.getItem().id; 
     if (draggedId !== props.id) { 
      props.swapItems(draggedId, props.id); 
     } 
    } 
}; 


const DragSourceDecorator = DragSource(ItemTypes.ITEM, itemSource, (connect, monitor) => { 
    return { 
     connectDragSource: connect.dragSource(), 
     isDragging: monitor.isDragging(), 
    }; 
}); 

const DropTargetDecorator = DropTarget(ItemTypes.ITEM, itemTarget, (connect) => { 
    return {connectDropTarget: connect.dropTarget()}; 
}); 

class SwagBagItem extends React.Component { 
    constructor(props) { 
     super(props); 

     this._handleDelete = this._handleDelete.bind(this); 
    } 

    componentWillReceiveProps(nextProps) { 
     const swagbagItemCpy = Object.assign({}, nextProps.swagbagItem); 
     delete swagbagItemCpy.id; 

     if (nextProps) { 
      sdk.put(`swagbags/${nextProps.swagbag.id}/items/${nextProps.swagbagItem.id}`, swagbagItemCpy) 
       .done((result) => { 
        console.log(result); 
       }).fail((error) => { 
        console.log(error); 
       }) 
      ; 
     } 
    } 

    _handleDelete(event) { 
     event.preventDefault(); 
     event.stopPropagation(); 

     if (confirm('Are you sure you want to delete this Swagbag Item?')) { 
      sdk.delete(`swagbags/${this.props.swagbag.id}/items/${this.props.swagbagItem.id}`) 
       .done(() => { 
        console.log('Swagbag Item remove!'); 
       }).then(() => { 
        this.props.loadSwagBags(); 
       }); 
      } 
     } 

    render() { 
     const {swagbagItem} = this.props; 
     return this.props.connectDragSource(this.props.connectDropTarget(
      <tr className="swagbag-item"> 
       <td>{swagbagItem.id}</td> 
       <td><Link to={`${this.props.swagbag.id}/items/${swagbagItem.id}`}>{swagbagItem.name}</Link></td> 
       <td>{swagbagItem.uri}</td> 
       <td> 
        <div className="btn-group btn-group-xs pull-right" role="group"> 
         <Link to={`${this.props.swagbag.id}/items/${swagbagItem.id}/edit`} className="btn btn-info">Edit</Link> 
         <Link to={`${this.props.swagbag.id}/items/${swagbagItem.id}`} className="btn btn-info">View</Link> 
         <button className="btn btn-danger btn-xs" onClick={this._handleDelete}>Remove</button> 
        </div> 
       </td> 
      </tr> 
     )); 
    } 
} 


SwagBagItem.propTypes = { 
    loadSwagBags: PropTypes.func, 
    params: PropTypes.object, 
    swagbag: PropTypes.object, 
    swagbagItem: PropTypes.object, 
}; 

export default DropTargetDecorator(DragSourceDecorator(SwagBagItem)); 

持有这些物品的容器或列表:

import React, {PropTypes} from 'react'; 
import {Link} from 'react-router'; 
import {DragDropContext} from 'react-dnd'; 
import HTML5Backend from 'react-dnd-html5-backend'; 
import sdk from '../../js/sdk'; 

import Nav from '../Nav'; 

import SwagBagItem from '../SwagBagItem'; 

class SwagBagItemsList extends React.Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      swagbag: null, 
      swagbagItems: [], 
     }; 

     this._loadSwagBags = this._loadSwagBags.bind(this); 
     this._compareItems = this._compareItems.bind(this); 
     this._swapItems = this._swapItems.bind(this); 
    } 

    componentWillMount() { 
     this._loadSwagBags(); 
    } 

    _compareItems(item1, item2) { 
     return item1.orderNumber - item2.orderNumber; 
    } 

    _swapItems(itemNo1, itemNo2) { 
     const items = this.state.swagbagItems; 
     let item1 = items.filter(item => item.id === itemNo1)[0]; 
     let item2 = items.filter(item => item.id === itemNo2)[0]; 
     let item1Order = item1.orderNumber; 
     item1.orderNumber = item2.orderNumber; 
     item2.orderNumber = item1Order; 

     items.sort(this._compareItems); 
     this.setState({swagbagItems: items}); 
    } 

    _loadSwagBags() { 
     sdk.getJSON(`swagbags/${this.props.params.id}`) 
      .done((result) => { 
       this.setState({swagbag: result}); 
      }) 
      .then(() => { 
       sdk.getJSON(`swagbags/${this.props.params.id}/items?fields=id,name,summary,uri,itemImageFile,orderNumber`).done((results) => { 
        this.setState({swagbagItems: results}); 
       }); 
      }); 
    } 

    render() { 
     let swagbagItems = null; 
     if (this.state.swagbagItems) { 
      swagbagItems = this.state.swagbagItems.map((item) => { 
       return <SwagBagItem 
          loadSwagBags={this._loadSwagBags} 
          swagbag={this.state.swagbag} 
          swagbagItem={item} 
          key={item.id} 
          id={item.id} 
          swapItems={this._swapItems} 
         />; 
      }); 
     } 
     if (!this.state.swagbag) { 
      return <div>Loading...</div>; 
     } 
     return (
      <div> 
       <h1>Swagbag Items</h1> 
       <Nav swagbag={this.state.swagbag} /> 
       <table className="table"> 
        <thead> 
         <tr> 
          <th>id</th> 
          <th>name</th> 
          <th>uri</th> 
          <th></th> 
         </tr> 
        </thead> 
        <tbody> 
         {swagbagItems} 
        </tbody> 
       </table> 
       <Link to={`swagbags/createItem/swagbagid/${this.state.swagbag.id}`} className="btn btn-success">Add Item</Link> 
      </div> 
     ); 
    } 
} 

SwagBagItemsList.propTypes = { 
    params: PropTypes.object, 
}; 

export default DragDropContext(HTML5Backend)(SwagBagItemsList); 

它正在PUT请求,但它使数百只是移动一个物体而连续排列。我不知道为什么我的生活。这会对应用程序造成严重的延迟,并使其无法响应。我是否正确地做了这件事?如果是这样,那么解决方法是什么?

编辑#1:今天醒来,应用程序工作正常。不幸的是,这是在进行生产,所以在此之前,我必须重新创建800+ PUT请求的bug并找出结果。可能会给这个奖励。

回答

0

如果您希望在拖动完成后发送更新,则可以添加一个endDrag函数,您可以将其添加到您的DragSource(http://gaearon.github.io/react-dnd/docs-drag-source.html),该函数只会触发一次,并且只有在完成拖动后才会触发。所以,如果你componentWillReceiveProps删除您的API调用,并将其移动到源这样的:

const itemSource = { 
    beginDrag(props) { 
    return { 
     id: props.id, 
     swagbagId: props.swagbag.id, 
     swagbagItem: props.swagbagItem, 
    }; 
    }, 
    endDrag(props, monitor) { 
    const item = monitor.getItem(); 
    sdk.put(`swagbags/${item.swagbagId}/items/${item.swagbagItem.id}`, item.swagbagItem) 
     .done((result) => { 
      console.log(result); 
     }).fail((error) => { 
      console.log(error); 
     }) 
    ; 
    }, 
}; 

它应该只拨打电话一个时间(我不能完全预测,不知道什么是在swagbag和swagbagItem但我认为它应该)。请注意,我使用DragSource监视器(http://gaearon.github.io/react-dnd/docs-drag-source-monitor.html)中的getItem()函数来检索beginDrag后传入的内容。