对于使用redux-orm的聊天应用程序,我有以下模型。每个Conversation包含许多Messages,但一条消息只能属于单个Conversation。
export class Message extends Model {
static modelName = 'Message';
static fields = {
id: attr(),
text: attr(),
created: attr(),
from: fk('User'),
conversation: fk('Conversation', 'messages')
};
}
export class Conversation extends Model {
static modelName = 'Conversation';
static fields = {
id: attr(),
created: attr(),
};
}我使用下面的选择器来获取与他们各自的消息的对话列表。
export const getConversations = createSelector(
getOrm,
createOrmSelector(orm, session => {
return session.Conversation
.all()
.toModelArray()
})
);问题出在哪里?每个Conversation实例的Conversation属性是QuerySet,而不是Array,这使得传递ti组件时很难处理。
以下是我尝试过的解决方案:
messages模型的Conversation属性映射到使用messages.all().toModelArray()的Messages数组中。这给了我错误的Can't mutate a reverse many-to-one relation,即使我试图克隆对象。messages设置正确的值。这是可行的,但是在状态频繁变化的应用程序上创建所有这些新对象似乎是一个巨大的性能限制。我应该如何在这里实现我的目标?
发布于 2017-12-21 04:49:51
你应该能够做一些类似于:
return session.Conversation.all().toModelArray()
.map(c => ({
...c.ref,
messages: c.messages.toRefArray()
}))在你的选择器里。如果这不起作用,您可能需要包括更多的细节。使用初始的toModelArray不是免费的,您需要“查询”它们才能在选择器中使用它们。
通常,我不会只是像这样转储这些实体的整个存储内容,我会将它们细化到组件实际需要的内容:
import { pick } from 'lodash/fp'
// ...
const refineConversation = c => ({
...pick([ 'id', 'updatedAt' ], c),
messages: c.messages.toRefArray().map(refineMessages)
})
const refineMessages = m => ({
...pick([ 'id', 'author', 'text', 'updatedAt' ], m)
})
// ...
return session.Conversation
.all()
.toModelArray()
.map(refineConversation)虽然从组件的存储中抛出一个对象引用是很有诱惑力的,但是在该对象上有很多东西您的组件可能不需要呈现。如果有任何变化,组件必须重新呈现,并且您的选择器不能使用其回忆录数据。
记住,当您使用对象扩展(或Object.assign)时,您正在创建浅拷贝。是的,这是有代价的,但是任何超过第一级嵌套的都是使用引用,所以您就是不是克隆整件事。选择器的使用应该保护您不必在mapStateToProps中做太多的工作(在使用该数据进行第一次呈现之后)。
使用状态管理做出好的选择是很重要的,但是真正的性能影响可能来自其他来源(不必要的呈现、等待API交互等等)。
https://stackoverflow.com/questions/47913038
复制相似问题