我的redux商店看起来像这样:
threads: [ {id: 1, board: 1}, ...],
posts: [ {id: 1, thread: 1}, ...]
查看电路板将为商店添加20个线程。并且线程的每个页面都会向商店添加20个帖子。
除此之外,每秒都会有新的帖子和帖子自动进入。
呈现董事会的代码如下:
threads.filter(thread => thread.boardId == props.params.boardId)
因此,每次访问一个主板时,它都会过滤数百个主题。每个帖子都会过滤每个页面的数千个帖子。
这会导致性能问题的速度有多快,我怎样才能最好地避免它们?
我查看了reselect,但是当过滤器发生变化时,似乎必须重新计算每个视图。
答案 0 :(得分:0)
现在,让我们假设你需要它reselect。当你扩展时它是一个方便的工具,但它可以在需要时推出,而不会有太多的麻烦。
一种相当有用的方法(被提取到一个名为normalizr的同样有用的库中)是对象数组集合的规范化。考虑到您在问题中描述的状态,您应该明确检查其背后的逻辑。这样做为您的商店集合提供备用结构,这有助于选择单个元素,同时不会影响过滤的性能>显着。
直接进入,你的状态可能可能最终看起来像:
boards: {
entities: {
board0: { id: "board0", threads: [ thread2, thread4, ...], data: ... },
board1: { id: "board1", threads: [ thread0, thread3, ...], data: ... },
},
ids: [ board0, board1, ... ],
},
threads: {
entities: {
thread0: { id: "thread0", posts: [ post0, post4, ... ], data: ... },
thread1: { id: "thread1", posts: [ post2, post3, ... ], data: ... },
},
ids: [ thread0, thread1, ... ],
},
posts: {
entities: {
post0: { id: "post0", data: ... },
post1: { id: "post1", data: ... },
},
ids: [ post0, post1, ... ],
},
这有很多原因。首先,通过操作将传入的帖子和线程添加到状态,这意味着您可以轻松地将它们标准化为进入。不是将完整的线程对象直接放入threads
数组,而是将其添加到threads.entities.<threadId>
并使用它的ID更新boards.<currentBoardId>.threads
数组。传入的post
对象也是如此。就这样,它已经正常化了。
现在,在显示组件时,每个board
都有一个非常轻量级的名为threads
的列表。而不是对长度为boards * threads
的数组进行过滤,而是只有在此板上可见的线程ID数组上的映射,以及本质上很快的字典查找。
可见板的线程:
const boardThreads = boards.entities[props.params.boardId].threads
.map(threadId => threads.entities[threadId]
所选主题的帖子:
const threadPosts = threads.entities[selectedThreadId].posts
.map(postId => posts.entities[postId])
每个集合的额外ids
字段不是必需的,但我发现它很有用。例如,列出所有董事会:
const allBoards = boards.ids.map(id => boards.entities[id])
然而,这可以使用Object.keys
功能来完成。直到开发。
应该说,这更像是一个简单的数组过滤器,并且可能需要考虑将新对象添加到状态中。但是,我提供的三个示例包括 no array filtering ,并且存储中使用的所有数组都只是ID数组(通常是非常简单的字符串)。此外,这可确保与实体关联的数据仅存储在一个地方(collection.entities
),即使在增长状态下也能保持状态的精益和一致性