-1

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())
b2ok
  • 544
  • 6
  • 13
  • 1
    I see a server 500 error on that endpoint. Can you [edit] the post to clarify *what* state specifically is empty that you refer to? See [mcve]. Interestingly enough your original endpoint *does* return data. – Drew Reese May 04 '23 at 17:09
  • @Drew Reese I edited endpoint. Try now. – b2ok May 04 '23 at 18:18
  • 1
    So the endpoint is working and returns data. What is the issue after this? – Drew Reese May 04 '23 at 18:21
  • 1. in postsSlice console.log('fetchPosts response:', response) is ok, array of posts 2. after dispatch(fetchPosts()) in PostsList nothing dispatch to state – b2ok May 04 '23 at 18:25
  • 1
    What is "PostsList"? What are you expecting to be dispatched to state? Can you add the `postsSlice` code to your [mcve]? – Drew Reese May 04 '23 at 18:27
  • Thanks for updating the post. I don't see any overt issues with the code. Are you saying that `dispatch(fetchPosts())` isn't being executed, so the thunk isn't run and nothing is fetched? Or is it dispatched and the posts are fetched and the correct state isn't being selected? Can you add to your post how you are creating the Redux store and combining the reducers to form the state tree? – Drew Reese May 04 '23 at 20:02

1 Answers1

0

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: { },

b2ok
  • 544
  • 6
  • 13