0

Hi folks I am new to React just learning reduxjs/toolkit for application state management. I have created simple application for handling posts. Currently what I am doing is loading list of posts using async Thunk called fetchPosts. My async thunk is being called twice on application load and I have literally no idea what is making to do so. I am using react version 18.2.0 and here is my post slice.

import { createAsyncThunk, createSlice, nanoid } from "@reduxjs/toolkit";
import {sub} from 'date-fns';
import axios from 'axios';

const POST_URL = 'http://jsonplaceholder.typicode.com/posts';


const initialState = {
   posts : [],
   status : 'idle',
   error : null     
 };

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {

const response = await axios.get(POST_URL);
return response.data;
});

const postsSlice = createSlice({
name: 'posts',
initialState,
reducers:{
    postAdded: {
        reducer(state, action) {
        state.posts.push(action.payload);
        },
        prepare(title,content, userId){
            return {
                payload:{
                    id: nanoid(),
                    title,
                    content,
                    userId,
                    date: new Date().toISOString(),
                    reactions: {
                        thumbsUp: 0,
                        wow:0,
                        heart:0,
                        rocket:0,
                        coffee:0
                    }
                }
            }
        }
    },
    reactionAdded(state, action) {
        const {postId, reaction} = action.payload;
        const existingPost = state.posts.find(post => post.id === postId);
        if (existingPost) {
            existingPost.reactions[reaction]++;
        }
    }
},
extraReducers(builder){
    builder.addCase(fetchPosts.pending, (state, action) => {
        state.status = 'loading';
        
    })
    .addCase(fetchPosts.fulfilled, (state, action) => {
        state.status = 'succeeded';
        let min = 1;
        const loadedPosts = action.payload.map(post => 
            {
                post.date = sub(new Date(), {minutes: min++}).toISOString();
                post.reactions = {
                    thumbsUp: 0,
                    wow: 0,
                    heart:0,
                    rocket:0,
                    coffee:0
                }
                return post;
            });
        state.posts = loadedPosts;
    })
    .addCase(fetchPosts.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message
    })
}
});

export const {postAdded,reactionAdded} = postsSlice.actions;
export const selectAllPosts = (state) => state.posts.posts;
export const getPostsStatus = (state) => state.posts.status;
export const getPostsError = (state) => state.posts.error;
export default postsSlice.reducer;

And here is my Post list component.

import React from 'react'
import { useSelector, useDispatch } from 'react-redux';
import { selectAllPosts, getPostsError, getPostsStatus, fetchPosts } from './postsSlice';
import { useEffect } from 'react';
import PostExcerpt from './PostExcerpt';
const PostsList = () => {
const dispatch = useDispatch();

const posts = useSelector(selectAllPosts);
const postStatus = useSelector(getPostsStatus);
const postError = useSelector(getPostsError);


useEffect(() => {
console.log('post status: ', postStatus);
  if(postStatus === 'idle')
  {
    dispatch(fetchPosts());
  }
},[postStatus])

let content;
if(postStatus === 'loading'){
console.log('loading');
content = <p>"Loading..."</p>
}
else if(postStatus === 'succeeded'){
console.log('succeded');
const orderedPosts = posts.slice().sort((a,b) => b.date.localeCompare(a.date));
content = orderedPosts.map(post => <PostExcerpt key={post.id} post={post}/>);
}
else if (postStatus === 'failed'){
content = <p>{postError}</p>;
}

return (
<section>
<h2>Posts</h2>
{content}
</section>
);
 }
 export default PostsList
Malik
  • 65
  • 2
  • 9

1 Answers1

1

So this was happening due to the mount -> unmount -> remount behaviour of component implemented in react version 18 useEffect.

Malik
  • 65
  • 2
  • 9