CreateAsyncThunk is no working when I refresh the page

Viewed 292

I'm trying to practise createAsyncThunk with reduxjs/tookit. When I first fetch the data from the api it works and I can render the data. However, when I refresh the page I get "TypeError: Cannot read properties of undefined (reading 'memes')" error and can't get it worked anymore. I looked up for some info and thought passing dispatch as useEffect dependency would help but it didn't. When I open Redux Devtools extension => diff = I can clearly see that I fetched the data, promise fulfilled and everything is fine. I try to log allMemes to console and it shows an empty object.

store.js

import { configureStore } from "@reduxjs/toolkit";
import memeSlice from "./features/getAllMemes/displayAllMemesSlice";
const store = configureStore({
    reducer:{
        memes:memeSlice
    }
});

export default store;

DisplaySlice.js

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const loadAllMemes = createAsyncThunk("getMemes/loadAllMemes", async () => {
     try {
        const response = await fetch("https://api.imgflip.com/get_memes");
        const data = await response.json();
        return data;
    } 
    catch (error) {
        console.log(error)
    }
})

export const memeSlice = createSlice({
    name:"getMemes",
    initialState: {
        isLoading:false,
        hasError:false,
        allMemes:{},
    },

    extraReducers: {
        [loadAllMemes.pending]:(state, action) => {
            state.isLoading = true;
        },
        [loadAllMemes.fulfilled]:(state, action) => {
            state.allMemes = action.payload;
            state.isLoading = false;
        },
        [loadAllMemes.rejected]:(state, action) => {
            state.hasError = true;
            
        }
    }
})
export default memeSlice.reducer;
export const selectAllMemes = state => state.memes.allMemes;

displayAllMemes.js

import React , {useEffect} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { loadAllMemes, selectAllMemes } from './displayAllMemesSlice';

export default function DisplayAllMemes() {

    const allMemes = useSelector(selectAllMemes)
    const dispatch = useDispatch()

    useEffect(() => {
        dispatch(loadAllMemes())
        console.log(allMemes)
    }, [dispatch])
    
    return (
        <div>
            {allMemes.data.memes.map(item => (
                <h1>{item.id}</h1>
            ))}
        </div>
    )
}

1 Answers
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const loadAllMemes = createAsyncThunk("memes/getAllMemes", async () => {
  try {
    const response = await fetch("https://api.imgflip.com/get_memes");
    const data = await response.json();
    return data;
  } catch (error) {
    console.log(error);
  }
});

export const memeSlice = createSlice({
  name: "memes",
  initialState: {
    isLoading: false,
    hasError: false,
    allMemes: {},
  },

  extraReducers: {
    [loadAllMemes.pending]: (state, action) => {
      state.isLoading = true;
    },
    [loadAllMemes.fulfilled]: (state, action) => {
      const { data, success } = action.payload;
      state.allMemes = data;
      state.isLoading = false;
    },
    [loadAllMemes.rejected]: (state, action) => {
      state.hasError = true;
    },
  },
});

export const {} = memeSlice.actions;
export default memeSlice.reducer;


-- root reducer
import { combineReducers } from "redux";
import memes_slice from "./memes_slice";


const reducer = combineReducers({   
  memes: memes_slice,
});

export default reducer;

-- Component 

import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { loadAllMemes } from "../../app/memes_slice";

function Memes() {
  const { allMemes } = useSelector((state) => state.memes);
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(loadAllMemes());
  }, [dispatch]);

  console.log(allMemes.memes);

  return <div>Memes</div>;
}

export default Memes;
Related