我想渲染一棵树,RenderItem 是树的节点,可以不断嵌套子节点,构建好这棵树后,会把根节点 RenderItem 传给 react-sortable-tree 去渲染。
type RenderItem = {id:string, name:string, children:RenderItem[]};
这棵树的源数据,也是树状的,但是组织方式是扁平的:
store: {
"111": {name:"node1", children_ids:["222", "333"]},
"222": {name:"node2", children_ids:["444"]},
"333": {name:"node3", children_ids:["555"]},
"444": {name:"node4", children_ids:[]},
"555": {name:"node5", children_ids:[]},
}
当某些操作,修改了源数据里的一小部分,Redux 会利用 immer 生成新的 store 。
这时候如果想要渲染某个节点,就要利用 Redux 的 useSelector ,根据新的 store 生成新的 RenderItem 树🌲。
问题的关键在于,如果我只修改了某个节点的很小一部分数据,就重新生成整个 RenderItem 树🌲,会感觉效率很低。所以有没有办法使用 reselect 这种库,缓存节点的渲染数据呢?
我试了试,发现很难,比如我想到的方案
var selectNode = createSelector(
(state, node_id)=>state[node_id],
(state, node_id)=>node_id,
(node, node_id)=>{
var childrenItems = node.children_ids.map((child_id)=>selectNode(state(从哪里来?), child_id));
var item:RenderItem = {id:node_id, name:node.name, children: childrenItems};
return item;
}
)
从上面代码可以看到,selectNode 嵌套调用时,总是需要 state 这个参数的,而 state 又总是变化的,也就导致了整个树的数据都要重新生成。
不知道我说清楚了没。这里不要纠结于 reselect 默认只能缓存 1 个数据,就假设它可以缓存很多个。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.