【问题标题】:drag to reorder and save state with reactjs拖动以重新排序并使用 reactjs 保存状态
【发布时间】:2020-03-12 07:30:58
【问题描述】:

我正在编写一个使用 react-sortable-hoc 的小应用程序

一切都很好,但我在显示按 order

排序的列表时遇到问题

我有

user 0
user 1
user 2

当我将用户 2 拖到用户 0 上方时 而不是得到

user 2
user 0
user 1

我明白了

user 2
user 1
user 0

我认为这与我在该州设置订单的方式有关。但我想不通。

这就是我在排序结束时设置顺序的方式

const onSortEnd = ({ oldIndex, newIndex }) => {

    setUsers(prevState => {
        const newItems = [...prevState];
        newItems[newIndex].order = oldIndex;
        newItems[oldIndex].order = newIndex;
        return newItems.sort((a, b) => a.order - b.order);
    })
};

这是正在运行的应用程序,因此您可以使用它。 https://codesandbox.io/s/winter-https-xelrd?fontsize=14&hidenavigation=1&theme=dark

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    我已经解决了, 这是与https://codesandbox.io/s/quizzical-colden-rm62y一起玩的工作网址

    您猜对了,问题出在onSortEnd 函数上。我们只需要将它们向上或向下冒泡,而不是交换 newIndex 和 oldIndex 位置。

    这是一个工作代码,可以稍微清理一下,但你明白了:)

    const onSortEnd = ({ oldIndex, newIndex }) => {
        setUsers(prevState => {
          const newItems = [...prevState];
    
          if (oldIndex > newIndex) {
            for (let i = oldIndex - 1; i >= newIndex; i--) {
              newItems[i].order++;
              newItems[oldIndex].order = newIndex;
            }
          } else if (oldIndex < newIndex) {
            for (let i = oldIndex + 1; i <= newIndex; i++) {
              newItems[i].order--;
              newItems[oldIndex].order = newIndex;
            }
          }
          return newItems.sort((a, b) => a.order - b.order);
        });
      };
    

    希望对您有所帮助。快乐编码:)

    【讨论】:

    • 我不明白,但它有效。让我喝杯咖啡再读一遍:) :)
    • Ok :) 它只是遍历所有元素并向上或向下一一移动,然后最后将拖动的元素移动到新位置:)
    • nice... 我只需要 console.log 那些改变的(因为我会保存到数据库中)你能帮忙吗?谢谢!
    • 你的想法... const newItems = [...prevState];常量更改 = [] newItems[oldIndex].order = newIndex;改变.push(newItems[oldIndex]); if (oldIndex > newIndex) { for (let i = oldIndex - 1; i >= newIndex; i--) { newItems[i].order++; changed.push(newItems[i]) } } else if (oldIndex a.order - b.order); });
    • 哦,喜欢 cmets 中的 SO 格式。对此感到抱歉。
    【解决方案2】:

    你所做的就是交换。

    如果您只想“插入”新位置的元素,则必须更新两个位置之间的所有项目。

    在您的情况下,一种方法是移动元素并为所有项目重新创建订单

    setUsers(prevState => {
      const newItems = [...prevState];
      newItems.splice(newIndex, 0, newItems.splice(oldIndex, 1)[0]).forEach((item,index)=>{
        item.order = index;
      });
    
      return newItems
    });
    

    https://codesandbox.io/s/confident-river-mrh3p的演示

    【讨论】:

    • 这个例子不起作用。我不仅在谈论新元素。这很“简单”,因为我只是将它添加到数组的末尾(顺序为:array.length)
    • @handsome 我在答案中发布的代码工作正常,我发布的链接存在问题(它没有保存我的代码)。我已经更新了链接。
    • 是的,我以前也遇到过。 codeandbox 需要自动保存 :) 所以.. 你正在更新所有元素对吗?
    • 我也没有看到更新的 .order 我需要它,因为我将所有内容都发送到数据库以保留这些东西
    • forEach 内部是更新order 的地方。
    【解决方案3】:

    看起来您的代码只是在交换元素。这似乎不是您真正想要做的。实际上,您确实想删除元素并将其插入给定位置。我想既然你已经有了 oldIndex 和 newIndex,你可以按如下方式处理排序函数:

      const onSortEnd = ({ oldIndex, newIndex }) => {
        setUsers(prevState => {
          var newItems = [...prevState];
          let elem = newItems[oldIndex]
          newItems.splice(oldIndex, 1)
          newItems.splice(newIndex, 0, elem)
    
         return newItems 
        });
      };
    

    实际上不需要订单,并且捕获的状态超出了所需的最低状态(除非您在其他地方使用它)。

    【讨论】:

    • 是的,需要订单,因为我需要保存到数据库,这样我才能保持状态。谢谢!
    • @handsome 不过,@Danny 所说的话是有道理的。由于使用数组,因此无需在 UI 中保留 order,并且数组是有序类型。
    • true 但我需要以正确的顺序将数据保存在数据库中,并且由于我无法删除和添加记录以保持订单,因此我需要使用订单密钥。谢谢!
    猜你喜欢
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多