Sortable: React + Redux problem

Created on 11 Jul 2016  路  11Comments  路  Source: SortableJS/Sortable

Hello,

I'm trying to use Sortable in Chrome extension based on React + Redux.
It all looks well when I'm dragging list items.
But when I save list order to redux store, list got rerendered and the elements I've swpaped are swapped again. So the order in store is correct, but

Do you have any idea to fix this?

help-wanted

Most helpful comment

@MrBlenny

    onMove(e, oe){
          const fromIndex = e.dragged.getAttribute('data-index')
          let toIndex = e.related.getAttribute('data-index') || -1
          const hoverClientY = oe.clientY - e.relatedRect.top
          const hoverMiddleY = (e.relatedRect.bottom - e.relatedRect.top) / 2
          if (toIndex === -1)
            toIndex = 0
          else{
            if (fromIndex - 1 === toIndex && hoverClientY > hoverMiddleY)
              return false

            if (fromIndex + 1 === toIndex && hoverClientY < hoverMiddleY)
              return false

            toIndex = toIndex + (hoverClientY > hoverMiddleY ? 1 : 0)
          }
          that.props.onUpdate(
            fromIndex,
            toIndex
          )
          e.dragged.setAttribute('data-index', toIndex)

          return false
        }

For this to actually work, we used a fork https://github.com/joual/Sortable/commits/master, where the original event is added to onMove.

All 11 comments

No ideas.

I think I've found where is the problem, but still can't solve it.

I'm giving each element of an unique key. When I swap two elements with Sortable, React doesn't know that keys were swapped and after store changes React re-render new elements in old positions.

It all works great when I use random keys, but I'd really like to avoid that as this way each time I'm re-rendering every element of the list.

I've had to do the exact same thing as you. Please let me know if you come up with a solution and I will do the same.

We had the same problem before. We ended up with using onMove, dispatch the action and return false, so it doesn't actually change the dom, it just fires the action, change the store and re-render by react.

@dkuang1980 Can you supply for reducer/action and onMove functions?

@MrBlenny

    onMove(e, oe){
          const fromIndex = e.dragged.getAttribute('data-index')
          let toIndex = e.related.getAttribute('data-index') || -1
          const hoverClientY = oe.clientY - e.relatedRect.top
          const hoverMiddleY = (e.relatedRect.bottom - e.relatedRect.top) / 2
          if (toIndex === -1)
            toIndex = 0
          else{
            if (fromIndex - 1 === toIndex && hoverClientY > hoverMiddleY)
              return false

            if (fromIndex + 1 === toIndex && hoverClientY < hoverMiddleY)
              return false

            toIndex = toIndex + (hoverClientY > hoverMiddleY ? 1 : 0)
          }
          that.props.onUpdate(
            fromIndex,
            toIndex
          )
          e.dragged.setAttribute('data-index', toIndex)

          return false
        }

For this to actually work, we used a fork https://github.com/joual/Sortable/commits/master, where the original event is added to onMove.

A simple yet dirty hack is to use this.state = newState inside onEnd callback instead of this.setState(newState). Eslint warning will appear and code reviewer is likely to blow its mind, but it works.

Sorry, actually it won't work with Redux, BTW.

major kudos @dkuang1980 . we used a similar solution but also forked sortable to allow it to send all move events and not just events that are moves onto a new element--the default behavior allowed a minor case where an item was dragged onto an item and then back (while being held) to move to the first place it was dragged to.

@RubaXa This issue hasn't been resolved. Do you mind reopening?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kevinvanmierlo picture kevinvanmierlo  路  3Comments

dwburdick picture dwburdick  路  3Comments

rakeshrockb picture rakeshrockb  路  3Comments

kinjal-codes picture kinjal-codes  路  3Comments

binitghetiya picture binitghetiya  路  4Comments