react 如何最好的实现对列表的增删操作?

2017-03-26 23:06:00 +08:00
 elone

我现在在做一个题库项目,一个题库可以对应数道题目,数量多时应该可以是几千上万道题。 现在的搭配是 react+redux+antdesign 在设计这个后台管理系统。 但是有一点我想请教一下各位。 比如说,在为题库新添加题目时,是怎么样个流程比较合适,我有两个想法:

一、

1 、添加 /删除 题目,客户端发起一个请求,服务端处理完毕返回。

2 、待返回后,客户端再发起一个请求,请求返回所有题目的新数据 ,以此新数据来更新客户端列表。

二、

1 、添加 /删除 题目,客户端发起一个请求,服务端处理完毕返回。

2 、由客户端将新添加的数据插入(删除)到原数据中,以此起到更新数据的作用。

第一种要发起两个请求才能完成一件事,第二种只要一个请求,但实现起来有点麻烦。

麻烦就麻烦在于,如何插入,以及如何删除列表中指定的数据 。

我本来是这样写的:

 handlerOk = (sourceData) => {
    if ( typeof(sourceData) !== "undefined") {
           //此处为一个 redux action
            this.props.setQuestions(this.props.questions.concat(sourceData));
    }
}

this.props.questions  为原始数据 
sourceData 为新添加的数据项
都为对象列表
[{id:1,name"test1"},  {id:2,name"test2"},  {id:3,name"test3"},   ]

以上代码确实可以在不请求服务器的情况下更新数据到原始数据中。但是有一个问题,就是插入的数据如果与原始数据项有重复项的时候,是会报错的,因为我采用 id 为 key ,而 key 在渲染时有重复是会报错的。 而如果要排除重复项,因为是对象列表, indexOf 似乎是无效的。只能一个一个遍历对比,感觉这样下来,如果数据量大的时候,应该相当费力。

以前使用 jquery 时,直接操作 dom 虽然粗暴却很容易 。现在使用 react ,感觉不太适应。请各位指点一下,我的需求就是说: 一个展示 列表,有一个新增按钮,删除按钮,当新增时,可以把新添加的数据项更新到列表中,而不用发起请求刷新全部数据。

8148 次点击
所在节点    React
13 条回复
vizards
2017-03-27 01:06:59 +08:00
既然用了 antd 为嘛不考虑直接用 antd 的表格啊
elone
2017-03-27 06:39:39 +08:00
@vizards 有在用啊
ghostheaven
2017-03-27 07:13:45 +08:00
如果数据量不是非常大的话建一个 id->data 的哈希表,每次添加删除的时候都查询一下
des
2017-03-27 07:42:47 +08:00
1 、换成对象,用 id 做 key
2 、手工指定对象本身为 key , indexOf 这个对象是没问题的。

还有为什么会有重复的?你确定不是 bug ?
ChefIsAwesome
2017-03-27 07:44:39 +08:00
不懂你的问题。你添加了之后 id 怎么能重复的
serco
2017-03-27 09:58:46 +08:00
问题的 id 是客户端生成的还是服务端,如果客户端生成,生成的时候就该生成一个 unique id 。如果是服务端生成的,又怎么会出现重复。

你自己说的第一种方式,可以在步骤一就返回全部的新数据,完全没必要两次请求。
但是你也说了数据可能会有很多,每次增删改查都返回全部数据显然并不合适。
elone
2017-03-27 11:17:25 +08:00
id 为数据库的 id 。关于重复 id 的事情也许是我的设计问题吧。有一个列表 A ,展示已关联的题目,(比如此时有列表项{id:1}{id:2}),有一个新增按钮,点击后出现所有题目列表以待选择,选择后如上所说,将新选择的题目更新到列表 A 中,如果不幸还选择了 id 为 1 的选项,当返回给列表 A 时就会出现重复的问题了。

不过这应该是我设计上的缺陷吧,应该在所有列表中禁用已关联的题目,使其不能选择。只不过似乎又要遍历才能对比出哪些题目已关联。


手机码字,不知道是否有表达清晰,😂
elone
2017-03-27 12:24:21 +08:00
我现在这样做:
```
handlerOk = (sourceData) => {
if ( typeof(sourceData) !== "undefined") {
var newQ = this.props.questions.concat(sourceData);
newQ = array.uniqBy(newQ,`id`);
this.props.setItembankRelatedQuestions(newQ);
}
}
```
以后再考虑性能问题吧。感觉现阶段有点想太多了。
elone
2017-03-27 12:35:42 +08:00
至于 删除就这样:
this.props.setItembankRelatedQuestions(array.xorBy(this.props.questions,this.state.selectedRows,'id')
otakustay
2017-03-27 13:48:51 +08:00
首先我不太相信你的数据量真的会很大,万条以内做 filter 根据 id 找一下不会消耗什么时间的
其次删除用 filter ,添加用 concat ,这还是比较简单的
不建议同时维护一个 id 的 Set ,这种同步的代价比较大,除非你设计出一个 SortedSet 的结构来
elone
2017-03-27 14:12:43 +08:00
@otakustay 谢谢你。所以说我可能想太多了
otakustay
2017-03-27 14:18:58 +08:00
@elone 我做过万条数据排序的优化,大概知道这个耗时的量级,删除和插入复杂度比排序低得多,完全没问题的
sunber
2017-03-27 15:19:29 +08:00
如果 react 列表所需要的 key 使用的是服务器生成的,那么可以在请求添加成功时,服务器返回新增的 id ,应该不会和当前 store 里面的重复了吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/350480

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX