V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaoming1992
V2EX  ›  程序员

列表异步移除数据时出错怎么办?

  •  
  •   xiaoming1992 · 2020-03-22 21:21:52 +08:00 · 1178 次点击
    这是一个创建于 1718 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
    function Parent() {
      const [list, setState] = useState()
    
      const asyncRemove = (i) => {
        // 这儿 i 已经形成了闭包
        // 如果 i 之前的元素在异步函数 asyncFunction 执行过程中被移除
        // 那这儿的 then 的回调中的 i 就不是正确的 i 了
        asyncFunction()
          .then(() => {
            // 移除第 i 项
            const tempList = [...list]
            tempList.splice(i, 1)
            setState(list)
          })
      }
    
      return list.map((item, i) => (
        <Child data={item} onRemove={() => asyncRemove(i)} />
      ))
    }
    
    

    如果
    Child 1 在执行异步移除自身的时候
    Child 2 也触发了异步移除自身的事件
    当 Child 1 移除之后, Child 2 的 index 就不对了...
    我能想到的方法有两个:

    1. 一个异步方法在执行的时候, 屏蔽其他异步事件(用户体验差)
    2. 建立一套体系来管理这些已触发事件的 index, 数组变动时智能修正(臆想了一下, 不知道能不能实现, 感觉好复杂)

    大佬们能提供思路或经验吗?

    5 条回复    2020-03-30 14:48:18 +08:00
    crz
        1
    crz  
       2020-03-22 22:15:18 +08:00
    1. 删除的时候不要用索引,用特征值( id 、key 等)
    2. asyncFunction 里面不要直接删除数组元素,把修改过的值存到 state,( immutable )
    3. setState 用回调(最新值),回调里删除
    ----
    不用 immutable 也可以,asyncFunction 里返回修改过的 list,删除的时候用特征
    xiaoming1992
        2
    xiaoming1992  
    OP
       2020-03-22 22:35:24 +08:00
    @crz 谢谢
    怪我题目没说完整,其实不单单是删除,还有编辑。。。
    例如一个这样的数组:
    const initialState = [
    -- {
    -- -- a: 1,
    -- -- b: 2,
    -- -- c: 3,
    -- }
    ]
    (回复不支持多空格,就用 - 来维持格式了)
    如果在一个异步操作中修改属性 a,在另一个异步操作中修改属性 b 。
    你说的 1 (删除的时候用特征值),在仅删除操作的时候有效,但是编辑的时候仍然无效,似乎只能将这些属性分开;
    针对这种情况,你说的 3 似乎也没办法;
    2 的话我目前确实是这样做的啊,没有操作原 list,而是保存修改后的值
    xiaoming1992
        3
    xiaoming1992  
    OP
       2020-03-22 22:44:37 +08:00
    再加一点,其实写成 reducer,在异步操作之后 dispatch 事件可以实现功能,但是这样的话就只是业务代码,没法抽象出来。。。
    xiaoming1992
        4
    xiaoming1992  
    OP
       2020-03-23 00:33:41 +08:00 via Android
    是我自己没想明白,其实就是 Vuex 的 commit 和 dispatch 那一套
    crz
        5
    crz  
       2020-03-30 14:48:18 +08:00
    @xiaoming1992 用特征值是为了保证在处理过程中准确定位到数组元素,编辑的时候也是一样的呀
    比如用 id 作为特征(唯一),那么先用 id 在数组中找到元素,修改或者覆盖

    const item = _.find(arr, {id});
    item.a = newA;
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6029 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:06 · PVG 10:06 · LAX 18:06 · JFK 21:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.