Reputation: 6091
I am trying to pull posts from WordPress blog.
In console, I am only getting one log for Blog
component where this.props.posts
is empty object. It should have second log when state changes after action passes through the reducer. I can even see successful xhr request for the posts in inspector.
Following is the component where I am firing action.
import React, {Component} from 'react';
import {Link} from 'react-router-dom';
import {connect} from 'react-redux';
import {fetchPosts} from '../../action/index';
class Blog extends Component {
componentDidMount(){
this.props.fetchPosts();
}
render(){
console.log('Posts are: ',this.props.posts);
return (
<div>
<Link to="/posts/new"><button> Add a New Post </button> </Link>
</div>
);
}
}
function mapStateToProps(state){
return {
posts: state.posts
};
}
export default connect(mapStateToProps, {fetchPosts})(Blog);
Following is the reducer.
import FETCH_POSTS from '../action';
import _ from 'lodash';
function PostsReducer(state= {}, action){
switch(action.type){
case FETCH_POSTS:
console.log('reducer: ', action.payload.data);
return _.mapKeys(action.payload.data, 'id');
default:
return state;
}
}
export default PostsReducer;
Index file for the combined reducer is following:
import {combineReducers} from 'redux';
import PostsReducer from './posts_reducer';
const rootReducer = combineReducers({
posts: PostsReducer
});
export default rootReducer;
Here's the action creator file
import axios from 'axios';
export const FETCH_POSTS = 'fetch_posts';
const ROOT_URL = 'https://public-api.wordpress.com/rest/v1.1/sites/ishhaanpatel.wordpress.com/posts';
export function fetchPosts() {
const request = axios.get(`${ROOT_URL}`);
console.log('request is: ',request);
return {
type: FETCH_POSTS,
payload: request
};
}
export default fetchPosts;
Upvotes: 0
Views: 272
Reputation: 168
Your action is asynchronous, so you need to dispatch it through some middle-ware like redux-thunk. See "Async Actions" in the official docs.
When you dispatch a plain action you can simply return the object literal, like this:
const actionCreator = () => ({ type: 'ACTION' })
but you want to attach a response payload to your action, so you need to wait until the request promise resolves and (if you are using thunks) return a function that takes dispatch as argument, which returns the actual action payload:
const asyncActionCreator = () => dispatch => {
fetch('url')
.then(response => dispatch({type: 'ACTION', payload: response}))
}
See above links for a deeper explanation and examples.
// edit
In case you are unfamiliar with the ES6 syntax:
function asyncActionCreator() {
return function(dispatch) {
fetch('url')
.then(function(response) {
dispatch({type: 'ACTION', payload: response})
})
}
}
Upvotes: 2