Search code examples
javascriptreactjsreact-nativereduxtoolkit

Redux-persist, type error: undefined is not a function


This is my first implementation of redux, and redux-persist in react native. I got an error " type error: undefined is not a function", error comes when i tried map states. Implementing redux works fine. When i console log my states i got my initial state. I Tried to solve problem with documentation. Unfortunately I haven't found the cause of the error. Please kindly help me with this problem. All code is on: https://github.com/SusulAdam/Shopping-List_React-Native_Redux_TypeScript. Below are some code snippets where most likely there is a bug

App.txs

import React, { FunctionComponent } from 'react';
import { Provider } from 'react-redux';
import { store, appPersist } from 'app/redux/shoppingRedux';
import { Navigation } from 'app/components/Navigation';
import { PersistGate } from 'redux-persist/integration/react';

const App: FunctionComponent = () => {
    return (
        <Provider store={store}>
            <PersistGate loading={null} persistor={appPersist}>
                <Navigation />
            </PersistGate>
        </Provider>
    );
};

export default App;

shoppingRedux.ts:

import { configureStore, createSlice, PayloadAction, getDefaultMiddleware } from '@reduxjs/toolkit';
import AsyncStorage from '@react-native-community/async-storage';
import {
    persistStore,
    persistReducer,
    FLUSH,
    REHYDRATE,
    PAUSE,
    PERSIST,
    PURGE,
    REGISTER,
} from 'redux-persist';
import 'react-native-get-random-values';
import { nanoid } from 'nanoid';

export interface ShoppingListType {
    id: string;
    desc: string;
    taken: boolean;
}

const shoppingListInitialState: ShoppingListType[] = [
    {
        id: nanoid(),
        desc: 'milk',
        taken: false,
    },
    {
        id: nanoid(),
        desc: 'bread',
        taken: false,
    },
];

const shoppingListSlice = createSlice({
    name: 'shoppingList',
    initialState: shoppingListInitialState,
    reducers: {
        create: {
            reducer: (
                state,
                { payload }: PayloadAction<{ id: string; desc: string; taken: boolean }>
            ) => {
                state.push(payload);
            },
            prepare: ({ desc }: { desc: string }) => ({
                payload: {
                    id: nanoid(),
                    desc,
                    taken: false,
                },
            }),
        },
        edit: (state, { payload }: PayloadAction<{ id: string; desc: string }>) => {
            const editProduct = state.find((product) => product.id === payload.id);
            if (editProduct) {
                editProduct.desc = payload.desc;
            }
        },
        taken: (state, { payload }: PayloadAction<{ taken: boolean; id: string }>) => {
            const takenProduct = state.find((product) => product.id === payload.id);
            if (takenProduct) {
                takenProduct.taken = payload.taken;
            }
        },
        delete: (state, { payload }: PayloadAction<{ id: string }>) => {
            const idProduct = state.findIndex((product) => product.id === payload.id);
            if (idProduct !== -1) {
                state.splice(idProduct, 1);
            }
        },
    },
});

export const {
    create: createShoppingListCreator,
    edit: editShoppingListCreator,
    taken: takenShoppingListCreator,
    delete: deleteShoppingListCreator,
} = shoppingListSlice.actions;

export const { select: selectdShoppingProductCreator } = selectedShoppingProductSlice.actions;

const persistConfig = {
    key: 'root',
    storage: AsyncStorage,
    // whitelist: ['shoppingListSlice'],
};

const reducer = {
    shoppingList: persistReducer(persistConfig, shoppingListSlice.reducer),
};

const middleware = [
    ...getDefaultMiddleware({
        serializableCheck: {
            ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
        },
    }),
];

export const store = configureStore({
    reducer,
    middleware,
});

export let appPersist = persistStore(store);

MainScreen.tsx:

import React, { useState } from 'react';
import { StyleSheet, View, Text, TextInput, Button } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import {
    ShoppingListType,
    createShoppingListCreator,
    editShoppingListCreator,
    selectdShoppingProductCreator,
    takenShoppingListCreator,
    deleteShoppingListCreator,
} from 'app/redux/shoppingRedux';

interface ShoppingListState {
    shoppingList: ShoppingListType[];
    selectedProduct: string;
}

const MainScreen = () => {
    const shoppingList = useSelector((state: ShoppingListState) => state.shoppingList);

return (
        <>
            <View
                style={{
                    alignItems: 'center',
                    flex: 1,
                    backgroundColor: 'red',
                }}
            >
                {shoppingList.map((shoppingElement: any) => (
                    <View style={{ flexDirection: 'row', padding: 10 }} key={shoppingElement.id}>
                        <Text
                            style={shoppingElement.taken && { textDecorationLine: 'line-through' }}
                        >
                            {shoppingElement.desc}
                        </Text>
            
                    </View>
                ))}
            </View>
        </>
    );
};

export { MainScreen };



Solution

  • Problem resolved, The problem was in the file shoppingRedux.ts. Correct implementation part:

    const reducer = combineReducers({
        shoppingList: shoppingListSlice.reducer,
        selectedProduct: selectedShoppingProductSlice.reducer,
    });
    const middleware = [
        ...getDefaultMiddleware({
            serializableCheck: {
                ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
            },
        }),
    ];
    
    const persistdReducer = persistReducer(persistConfig, reducer);
    
    export const store = configureStore({
        reducer: persistdReducer,
        middleware: getDefaultMiddleware({
            serializableCheck: false,
        }),
    });
    
    export let appPersist = persistStore(store);