rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.95k stars 865 forks source link

TypeError: Cannot read property X of undefined #1321

Closed lucavallin closed 3 years ago

lucavallin commented 3 years ago

Hi there, I have spent the day trying to figure this out but I really can't. I am using redux toolkit and react native. My store looks like this:

import {
  combineReducers,
  configureStore,
  getDefaultMiddleware,
} from "@reduxjs/toolkit";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { persistStore, persistReducer } from "redux-persist";
import eventsReducer from "./eventSlice";

const rootReducer = combineReducers({
  events: eventsReducer,
});

const persistConfig = {
  key: "root",
  storage: AsyncStorage,
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: getDefaultMiddleware({
    serializableCheck: false,
  }),
});

export const persistor = persistStore(store);
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;

My events slice like this:

import {
  createAsyncThunk,
  createEntityAdapter,
  createSlice,
} from "@reduxjs/toolkit";
import { RootState } from "./store";
import { firestore, storage } from "../services/firebase";

export interface EventData {
  id: string;
  imageUrl: string;
  created: Date;
  labels: Array<{ description: string; score: number }>;
}

export const getEvents = createAsyncThunk("events/getEvents", async () => {
  const response = await firestore.collection("Events").get();
  return Promise.all(
    response.docs.map(async (d) => {
      const url = await storage.refFromURL(d.get("uri")).getDownloadURL();
      return {
        id: d.id,
        imageUrl: url,
        created: d.get("created").toDate(),
        labels: d.get("labels"),
      } as EventData;
    })
  );
});

export const eventsAdapter = createEntityAdapter<EventData>();

const eventsSlice = createSlice({
  name: "events",
  initialState: eventsAdapter.getInitialState({
    loading: false,
    events: [] as Array<EventData>,
  }),
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(getEvents.pending, (state) => {
      state.loading = true;
    });
    builder.addCase(getEvents.fulfilled, (state, action) => {
      eventsAdapter.setAll(state, action.payload);
      state.loading = false;
    });
    builder.addCase(getEvents.rejected, (state) => {
      state.loading = false;
    });
  },
});

export const { selectAll: selectAllEvents } = eventsAdapter.getSelectors(
  (state: RootState) => state.events
);

export default eventsSlice.reducer;

And my App.tsx returns this:

return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <NativeBaseProvider theme={theme}>
          <Navigation />
        </NativeBaseProvider>
      </PersistGate>
    </Provider>
  );

I have a component that renders a list of events. It works fine without redux-persist, but with it, my events are not there, triggering the TypeError when rendering. Any idea what I am doing wrong? Thank you!

lucavallin commented 3 years ago

Fixed: I have cleared application data from the browser.