Search code examples
reactjsreduxredux-thunk

Couldn't able to get data back from actionCreator


Lately i have been working around in redux and was trying to get my hands on, I tried async calling by redux-thunk.
I am showing the relevent files.
Posts.js
This file is calling getPosts() in componentdidmount which in return tries to get data from actionCreator.

 import React,{Component} from 'react'
import Axios from 'axios'
import CardPost from '../Post/Post'
import Container from 'react-bootstrap/Container'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
import classes from './Posts.module.css'
import {Link,Route} from 'react-router-dom'
import {connect} from 'react-redux'
import {getPost} from '../../Store/action/posts'
class Posts extends Component{


    componentDidMount(){
        this.props.getPosts()
    }

    render(){
        let post =<p>Loading data...</p>
       if(this.props.bulkPost.length>0){
           console.log("rendering again")
            post =  this.props.bulkPost.map((item)=>{
            return(

    <Col as={Link} to={"/posts/"+item.id} className={classes.topMargin} key={item.id} sm={4}> 
        <CardPost/>
    </Col>

            )

           })
       }
        return(
            <>
            <div>
                 <Container>
                        <Row> 
                            {post}
                        </Row>
               </Container>
            </div>

        </>
        )
    }
}

const mapStateToProps = state=>{
    return{ 
        bulkPost: state.pos.posts,
        // oneLineData: state.full.fetchedText
    }
}

const mapDispatchToProps = dispatch =>{
    return{

        // onDeleteResult: (id)=>dispatch(actionCreator.deleteResult(id)),
        getPosts:()=>dispatch(getPost())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Posts)  

This is my actionCreator posts.js
It utilizes redux thunk middleware and tries to get data Async, on checking by console.log(res), data is being fetched in the file.

    import {POSTS} from '../action/actionType'
import Axios from 'axios'

export const savePost = (res)=>{
    return{
        posts: res,
        type:POSTS

    }
}

export const getPost = ()=>{
    return (dispatch)=>{
        Axios.get("https://jsonplaceholder.typicode.com/posts/").then((response)=>{    
        dispatch(savePost(response.data));
        })
    }
}

And now the third file where the data should be ideally dispatched, and should be returned to us

    import * as actionType from '../action/actionType'
const intitalState = {
    posts:[]
}

const reducer = (state=intitalState, action)=>{
    switch(action.type){
        case actionType.POSTS:
                console.log(state)
                const post  = state.posts.slice(0,4);
                const updatedPost = post.map((post)=>{
                    return{
                    ...post
                    }
                })
                    return{
                        ...state,
                        posts:updatedPost
                    }
    }
    return state
}

export default reducer

Here the state posts is not being populated by dispatch method in the first file. Can someone please help, what i am doing wrong over here ?
Edit: this is the full working project online
https://codesandbox.io/s/4xwlwl70v0


Solution

  • In your actioncreator you can dispatch the action directly:

    import Axios from 'axios'
    import {POSTS} from '../action/actionType'
    
    export const getPost = ()=>{
        return (dispatch)=>{
            Axios.get("https://jsonplaceholder.typicode.com/posts/").then((response)=>{    
                dispatch({
                    type: POSTS,
                    posts: response.data
                });
            })
        }
    }
    

    In your reducer, you're mapping the results from the API-call. I don't see the purpose of mapping the result? The posts from the action creator is available on action.posts.

    import * as actionType from '../action/actionType'
    const initalState = {
        posts: []
    }
    
    const reducer = (state = initalState, action)=>{
        switch(action.type){
            case actionType.POSTS:
                const posts = action.posts.slice(0,4);
                return{
                    ...state,
                    posts: posts
                }
        }
        return state
    }
    
    export default reducer;
    

    Without seeing your combinedRecduers, is this a typo?

    const mapStateToProps = state=>{
        return{ 
            bulkPost: state.pos.posts, // maybe state.post.posts ?
            // oneLineData: state.full.fetchedText
        }
    }