使用react redux进行Firestore分页



我尝试使用firebase和react redux工具包添加分页。我理解这个逻辑,但在使用redux时遇到了麻烦。

起初我想将lastDoc设置为redux状态,但由于它是一个对象,所以出现了错误。

然后我改变了方式,开始将最后一个文档的id保持在该状态。但我无法获得火球doc本身

const lastDocRef = firestoreDB.doc(`catalog/${publishedBooks.lastDocId}`)

与不同

const lastDoc = snap.docs[snap.docs.length-1];

我感谢任何帮助如何解决这个问题。

import { createSlice, createAsyncThunk, createEntityAdapter } from '@reduxjs/toolkit';
import firebaseService from 'app/services/firebaseService';
const firestoreDB = firebaseService.firestoreDB;
export const getPublishedBooks = createAsyncThunk('adminApp/publishedBooks/getPublishedBooks',
async (params, { dispatch, getState }) => {
const promise = firestoreDB
.collection('catalog')
.orderBy('lastPublish', 'desc')
.limit(10)
.get()
.then(snap => {
const lastDoc = snap.docs[snap.docs.length-1];
dispatch(setLastDocId(lastDoc.id));
let books = [];
snap.forEach(bookDoc => {
const id = bookDoc.id;
const data = bookDoc.data();
const lastPublish = data.lastPublish.toDate().toISOString();
books.push({ ...data, id, lastPublish });
});
return books;
})
.catch(error => {
return {}
});
const result = await promise;
return result;
}
);
export const getPublishedBooksNext = createAsyncThunk('adminApp/publishedBooks/getPublishedBooksNext',
async (params, { dispatch, getState }) => {
const { publishedBooks } = getState().adminApp;
const lastDocRef = firestoreDB.doc(`catalog/${publishedBooks.lastDocId}`)
const promise = firestoreDB
.collection('catalog')
.orderBy('lastPublish', 'desc')
.startAfter(lastDocRef)
.limit(10)
.get()
.then(snap => {
const lastDoc = snap.docs[snap.docs.length-1];
dispatch(setLastDocId(lastDoc.id));
let books = [];
snap.forEach(bookDoc => {
const id = bookDoc.id;
const data = bookDoc.data();
const lastPublish = data.lastPublish.toDate().toISOString();
books.push({ ...data, id, lastPublish });
});
return books;
})
.catch(error => {
return {}
});
const result = await promise;
return result;
}
);
const publishedBooksAdapter = createEntityAdapter({});
const initialState = publishedBooksAdapter.getInitialState({
lastDocId: null
});
export const {
selectAll: selectPublishedBooks,
selectById: selectPublishedBookById,
selectTotal: selectPublishedBooksTotal
} = publishedBooksAdapter.getSelectors(state => state.adminApp.publishedBooks);
const publishedBooksSlice = createSlice({
name: 'adminApp/publishedBooks',
initialState,
reducers: {
resetPublishedBooks: (state, action) => initialState,
setLastDocId: {
prepare: doc => {
const payload = doc
return { payload };
},
reducer: (state, action) => {
state.lastDocId = action.payload;
}
},
resetLastDocId: {
prepare: () => {
const payload = null
return { payload };
},
reducer: (state, action) => {
state.lastDocId = action.payload;
}
},
},
extraReducers: {
[getPublishedBooks.fulfilled]: publishedBooksAdapter.setAll,
[getPublishedBooksNext.fulfilled]: publishedBooksAdapter.upsertMany
}
});
export const { resetPublishedBooks, setLastDocId, resetLastDocId } = publishedBooksSlice.actions;
export default publishedBooksSlice.reducer;

lastDocRef只返回单据引用。你需要得到真正的文档本身。

const lastDocRef = await firestoreDB.doc(`catalog/${publishedBooks.lastDocId}`).get();

您应该使用await而不是then-catch来获得更易读的代码。

export const getPublishedBooksNext = createAsyncThunk('adminApp/publishedBooks/getPublishedBooksNext',
async (params, { dispatch, getState }) => {
const { publishedBooks } = getState().adminApp;
try {
const lastDocRef = await firestoreDB.doc(`catalog/${publishedBooks.lastDocId}`).get();
const snap = await firestoreDB
.collection('catalog')
.orderBy('lastPublish', 'desc')
.startAfter(lastDocRef)
.limit(10)
.get()

const lastDoc = snap.docs[snap.docs.length-1];
let books = [];
dispatch(setLastDocId(lastDoc.id));
snap.forEach(bookDoc => {
const id = bookDoc.id;
const data = bookDoc.data();
const lastPublish = data.lastPublish.toDate().toISOString();
books.push({ ...data, id, lastPublish });
});
return books;
} catch (error) {
return {}
}
}
);

编辑:您还可以将lastDoc保存为redux,然后稍后引用它,以避免为lastDocRef获取额外的工作负载。

export const getPublishedBooksNext = createAsyncThunk('adminApp/publishedBooks/getPublishedBooksNext',
async (params, { dispatch, getState }) => {
const { lastDocRef } = getState().adminApp; // get saved lastDoc 

try {
const snap = await firestoreDB
.collection('catalog')
.orderBy('lastPublish', 'desc')
.startAfter(lastDocRef) // use it here. 
.limit(10)
.get()

const lastDoc = snap.docs[snap.docs.length-1];
let books = [];
// dispatch(setLastDocId(lastDoc.id)); // instead of saving the doc id 
dispatch(setLastDoc(lastDoc)); // save the last document instead 

snap.forEach(bookDoc => {
const id = bookDoc.id;
const data = bookDoc.data();
const lastPublish = data.lastPublish.toDate().toISOString();
books.push({ ...data, id, lastPublish });
});
return books;
} catch (error) {
return {}
}
}
);

最新更新