Blog>
Snippets

Merging Incoming Page Data with Existing State

Show how to write a reducer using Immer to immutably update state with newly fetched page data without losing the existing paginated data.
import { createSlice, current } from '@reduxjs/toolkit';

const initialState = {
    pages: [],
    pageCount: 0,
    isLoading: false,
    error: null
};

const paginationSlice = createSlice({
    name: 'pagination',
    initialState,
    reducers: {
        startLoading(state) {
            state.isLoading = true;
        },
        receivedPage(state, action) {
            const { newPage, pageNumber } = action.payload;
            if (!state.pages[pageNumber]) {
                state.pages[pageNumber] = newPage;
                state.pageCount = Math.max(state.pageCount, pageNumber + 1);
            } else {
                // Merge the new page with the current page
                state.pages[pageNumber] = {
                    ...current(state.pages[pageNumber]),
                    ...newPage
                };
            }
            state.isLoading = false;
        },
        errorLoading(state, action) {
            state.isLoading = false;
            state.error = action.payload;
        }
    }
});

export const { startLoading, receivedPage, errorLoading } = paginationSlice.actions;
export default paginationSlice.reducer;
This slice of state manages pagination, with the ability to load pages and merge new data into the existing state. If the page data for a specific page number does not exist, it is added. If the page number already exists, the data is merged using the spread operator, ensuring that the state is updated immutably thanks to the Immer library which Redux Toolkit uses internally. Actions are included for starting a load operation, successfully receiving a page, and handling errors.