简体   繁体   English

使用 react-redux 进行 Firestore 分页

[英]Firestore pagination with react-redux

I try to add pagination using firebase and react redux-toolkit.我尝试使用 firebase 添加分页并反应 redux-toolkit。 I get the logic but having trouble using it with redux.我明白了逻辑,但无法将其与 redux 一起使用。

At first I wanted to set lastDoc in redux state but I got error since it is an object.起初我想在 redux state 中设置 lastDoc 但我得到了错误,因为它是 object。

Then I changed the way and started to keep id of last document in the state.然后我改变了方式,开始在 state 中保留最后一个文档的id But then I can't get the firebase doc itself但是我无法获得 firebase文档本身

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

is not same with不一样

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

I appreciate any help how to solve this.我感谢任何帮助如何解决这个问题。

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 only returns the doc reference. lastDocRef只返回文档引用。 You need to get the actual doc itself.您需要获取实际的文档本身。

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

And you should use await instead of then-catch for more readble code.你应该使用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 {}
        }
    }
);

Edit: You can also save the lastDoc to redux then reference it later to avoid additional workload fetching for the lastDocRef.编辑:您还可以将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 {}
        }
    }
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM