Redux Toolkit Streaming 更新 - 如何处理关系实体适配器?

Redux Toolkit Streaming updates - how to deal with relational entity adapters?

我正在处理使用带有实体适配器的 RTK 查询的聊天。

我目前有 2 个不同的实体适配器;一个用于聊天,一个用于消息。

我怎样才能select发送特定聊天的所有消息?我需要在聊天适配器中存储消息 ID 数组,还是 select 所有消息并按 parent_chat_uuid 属性 过滤它们?

更有效的方法是什么?是否有内置的 selector 允许您通过其 属性 而不是 id 来 select 实体?我想象在非常大的数组上映射以查找具有某些 属性 的对象是非常昂贵的。

谢谢

编辑:

我最初查询最新的聊天记录,一旦 cacheDataLoaded,我就将许多聊天记录添加到实体适配器。

我还设置了 websocket 连接并在数据加载后订阅 'message' 事件。每次消息都由 ws I addOne 消息通知。如果通知 'delivered' 或 'read' 之类的状态,我会调用 updateOne。

我实际上正在尝试重写未使用 RTK 查询和实体适配器的项目,并且消息总是添加到聊天对象内的消息数组中。 Websocket 连接和更新由调用异步 thunk 的中间件处理 -> 更新存储。

我正在尝试移动所有中间件以在 rtk 查询/变异逻辑内部处理并直接从那里调用操作(或者使用更多逻辑调用操作的 thunk)。

** 题外话,我可以为此创建一个单独的 post,但是创建一个仅调用操作的 App Thunk(非异步)有什么好处吗?在这种情况下,我应该只调用操作吗?

我是一名 RTK 维护者,也是 createEntityAdapter 的“作者”(从技术上讲,我从 NgRX 移植了它,但我为此做了很多工作)。

实际上我自己在之前的项目中做过类似的事情。我会把代码的简化版本放到要点中,但我也会 post 在这里 post 也是为了post。

我使用的技术是嵌套实体适配器:一个 top-level 存储聊天室的技术,以及一个嵌套在每个房间条目内的存储该房间消息的技术:

// Example of using multiple / nested `createEntityAdapter` calls within a single Redux Toolkit slice

interface Message {
  id: string;
  roomId: string;
  text: string;
  timestamp: string;
  username: string;
}

interface ChatRoomEntry {
  id: string;
  messages: EntityState<Message>;
}

const roomsAdapter = createEntityAdapter<ChatRoomEntry>();
const messagesAdapter = createEntityAdapter<Message>();

const fetchRooms = createAsyncThunk(
  "chats/fetchRooms",
  chatsAPI.fetchRooms
);

const fetchMessages = createAsyncThunk(
  "chats/fetchMessages",
  async (roomId) => {
    return chatsAPI.fetchMessages(roomId);
  }
)

const chatSlice = createSlice({
  name: "chats",
  initialState: roomsAdapter.getInitialState(),
  reducers: {
  
  },
  extraReducers: builder => {
    builder.addCase(fetchRooms.fulfilled, (state, action) => {
      const roomEntries = action.payload.map(room => {
        return {id: room.id, messages: messagesAdapter.getInitialState()};
      });
      
      roomsAdapter.setAll(state, roomEntries);
    })
    .addCase(fetchMessages.fulfilled, (state, action) => {
      const roomId = action.meta.arg;
      const roomEntry = state.entities[roomId];
      if (roomEntry) {
        messagesAdapter.setAll(roomEntry.messages, action.payload);
      }
    })
  }
})

/*
Resulting state:
{
  ids: ["chatRoom1"],
  entities: {
    chatRoom1: {
      id: "chatRoom1",
      messages: {
        ids: ["message1", "message2"],
        entities: {
          message1: {id: "message1", text: "hello"},
          message2: {id: "message2", text: "yo"},
        }
      }
    }
  }
}
*/

也就是说,您的情况听起来有些不同,因为您明确表示您正在使用 RTK 查询 尝试流式传输某些内容。因此,我实际上不确定您是如何尝试设置端点和存储数据 atm。如果您可以编辑您的 post 更多详细信息然后发表评论,我可以尝试更新此回复以提供更多建议。

具体针对最后一个问题:不,没有 built-in 用于按属性搜索的选择器,这样做通常会变成“re-filter 所有项目只要有更新”。