javascript 如何在RTK查询中取消订阅Firebase onSnapShot?

lokaqttq  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(108)

我正在React Native中创建一个依赖于实时更新的应用程序。当用户在其会话中更新数据时,另一个用户需要立即看到该更新,而无需刷新其应用程序。我正在使用RTK Query来管理我的商店,但如果我在查询中使用onSnapShot,则无法确定如何解决内存泄漏问题。我是否需要考虑其他Redux解决方案?
我试过通过 prop 传递数据来管理数据,但是使用复杂的组件时,管理会变得有点复杂。
我从组件中的以下内容开始,但希望将其移到API中:

export const teamPlayersApi = createApi({
  reducerPath: "teamPlayers",
  baseQuery: fakeBaseQuery(),
  tagTypes: ["TeamPlayer"],
  endpoints: (builder) => ({
    fetchTeamPlayersByMatchId: builder.query({
      async queryFn(matchId) {
        let players = [];
        return new Promise((resolve, reject) => {
          const playersRef = query(
            collection(db, "teamPlayers"),
            where("playerMatchId", "==", matchId)
          );
          //real time update

          onSnapshot(playersRef, (snapshot) => {
            players = snapshot.docs.map((doc) => ({
              id: doc.id,
              player: doc.data()
            }));
            resolve({ data: players });
          });
        });
      }
    })
  })
})
7qhs6swi

7qhs6swi1#

这有两个不同的部分:

  • a queryFn使用onValue获取初始数据。这是查询进入loading状态并在某个点以第一个值结束的点。
  • onCacheEntryAdded生命周期函数,用于调用onSnapshot、更新值并保存订阅。在组件使用该高速缓存条目时,将在此处生成订阅并使用新值更新数据。
export const teamPlayersApi = createApi({
  reducerPath: "teamPlayers",
  baseQuery: fakeBaseQuery(),
  tagTypes: ["TeamPlayer"],
  endpoints: (builder) => ({
    fetchTeamPlayersByMatchId: builder.query({
      async queryFn(matchId) {
        let players = [];
        return {
          data: await new Promise((resolve, reject) => {
            const playersRef = query(
              collection(db, "teamPlayers"),
              where("playerMatchId", "==", matchId)
            );
            // probably more logic here to get your final shape
            onValue(
              playersRef,
              (snapshot) => resolve(snapshot.toJSON()),
              reject
            );
          }),
        };
      },
      async onCacheEntryAdded(
        matchId,
        { updateCachedData, cacheDataLoaded, cacheEntryRemoved }
      ) {
        let unsubscribe = () => {};
        try {
          await cacheDataLoaded;
          const playersRef = query(
            collection(db, "teamPlayers"),
            where("playerMatchId", "==", matchId)
          );
          unsubscribe = onSnapshot(playersRef, (snapshot) => {
            players = snapshot.docs.map((doc) => ({
              id: doc.id,
              player: doc.data(),
            }));

            updateCachedData((draft) => {
              // or whatever you want to do
              draft.push(players);
            });
          });
        } catch {}
        await cacheEntryRemoved;
        unsubscribe();
      },
    }),
  }),
});

相关问题