Search code examples
reactjsreduxservermockingthunk

dispatch(fetchPosts()) give empty state


Here is all ok, response.data is array:

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
  const response = await axios.get('https://640114a00a2a1afebee5c77d.mockapi.io/post1')
  console.log(response)
return response.data
})

Here is not, state is empty:

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

I try to use thunk in React Redux app with data on Mock server.

PostsList.js:

import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { selectAllPosts, fetchPosts } from './postsSlice'
import { Spinner } from '../../components/Spinner'

const PostExcerpt = ({ post }) => {
  return (
    <article className="post-excerpt" key={post.id}>
      <h3>{post.title}</h3>
      <p className="post-content">{post.content.substring(0, 100)} 
   </p>
    </article>
      )
    }

export const PostsList = () => {
  const dispatch = useDispatch()
  const posts = useSelector(selectAllPosts)
  console.log(posts)
  const postStatus = useSelector((state) => state.posts.status)
  const error = useSelector((state) => state.posts.error)

console.log(posts)

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

  let content

  if (postStatus === 'loading') {
    content = <Spinner text="Loading..." />
  } else if (postStatus === 'succeeded') {
    content = posts.map(post => (
      <PostExcerpt key={post.id} post={post} />
    ))
  } else if (postStatus === 'failed') {
    content = <div>{error}</div>
  }

  console.log(content)
return (
  <section>
    <h2>Posts</h2>
    {content}   
  </section>
)
}

postsSlice.js:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import axios from 'axios'

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

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () 
=> {
  const response = await 
axios.get('https://640114a00a2a1afebee5c77d.mockapi.io/post1')
  //console.log(response)
  console.log('fetchPosts response:', response)
  return response.data
})

console.log(fetchPosts)

export const addNewPost = createAsyncThunk(
  'posts/addNewPost',
  // The payload creator receives the partial `{title, content, user}` 
 object
  async (initialPost) => {
    // We send the initial data to the fake API server
    const response = await 
axios.post('https://640114a00a2a1afebee5c77d.mockapi.io/post1',  
initialPost)
    // The response includes the complete post object, including unique 
 ID
    return response.data
  }
)

const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {  
    extraReducers(builder) {
      builder
        .addCase(fetchPosts.pending, (state) => {
          state.status = 'loading'
        })
        .addCase(fetchPosts.fulfilled, (state, action) => {
          state.status = 'succeeded'
          // Add any fetched posts to the array
          state.posts = state.posts.concat(action.payload)
        })
        .addCase(fetchPosts.rejected, (state, action) => {
          state.status = 'failed'
          state.error = action.error.message
        })
        .addCase(addNewPost.fulfilled, (state, action) => {
          // We can directly add the new post object to our posts array
          state.posts.push(action.payload)
        })
      }
    }
  })

export default postsSlice.reducer

export const selectAllPosts = state => state.posts.posts

console.log(selectAllPosts)

export const selectPostById = (state, postId) =>
  state.posts.posts.find(post => post.id === postId)

I have been learning this https://redux.js.org/tutorials/essentials/part-5-async-logic There is local server, I use Mock server endpoint.

store.js:

import { configureStore } from '@reduxjs/toolkit';
import postsReducer from '../features/posts/postsSlice'

export const store = configureStore({
  reducer: {
    posts: postsReducer
  }
})
console.log(store.getState())

Solution

  • In postsSlice.js after the word reducer and the colon there is an open curly bracket that I did not close and put a comma after it.

    This is correct reducers: { },