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?
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.
Help wanted ---> https://github.com/SortableJS/react-sortablejs
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?
Most helpful comment
@MrBlenny
For this to actually work, we used a fork https://github.com/joual/Sortable/commits/master, where the original event is added to onMove.