In my store I have a state with this shape: {posts: [{...},{...}]}
, but when I use mapStateToProps()
in Home.js, the state returns {posts: []}
, with an empty array (where there used to be an array in the store's state).
Am I using mapStateToProps()
incorrectly or does the problem stem from other parts of the Redux cycle?
API fetch I'm using, temporarily located in actions.js
// api
const API = "http://localhost:3001"
let token = localStorage.token
if (!token) {
token = localStorage.token = Math.random().toString(36).substr(-8)
}
const headers = {
'Accept': 'application/json',
'Authorization': token
}
// gets all posts
const getAllPosts = token => (
fetch(`${API}/posts`, { method: 'GET', headers })
);
Action and action creators, using thunk middleware:
// actions.js
export const REQUEST_POSTS = 'REQUEST_POSTS';
function requestPosts (posts) {
return {
type: REQUEST_POSTS,
posts
}
}
export const RECEIVE_POSTS = 'RECEIVE_POSTS';
function receivePosts (posts) {
return {
type: RECEIVE_POSTS,
posts,
receivedAt: Date.now()
}
}
// thunk middleware action creator, intervenes in the above function
export function fetchPosts (posts) {
return function (dispatch) {
dispatch(requestPosts(posts))
return getAllPosts()
.then(
res => res.json(),
error => console.log('An error occured.', error)
)
.then(posts =>
dispatch(receivePosts(posts))
)
}
}
Reducer:
// rootReducer.js
function posts (state = [], action) {
const { posts } = action
switch(action.type) {
case RECEIVE_POSTS :
return posts;
default :
return state;
}
}
Root component that temporarily contains the Redux store:
// index.js (contains store)
const store = createStore(
rootReducer,
composeEnhancers(
applyMiddleware(
logger, // logs actions
thunk // lets us dispatch() functions
)
)
)
store
.dispatch(fetchPosts())
.then(() => console.log('On store dispatch: ', store.getState())) // returns expected
ReactDOM.render(
<BrowserRouter>
<Provider store={store}>
<Quoted />
</Provider>
</BrowserRouter>, document.getElementById('root'));
registerServiceWorker();
Main component:
// Home.js
function mapStateToProps(state) {
return {
posts: state
}
}
export default connect(mapStateToProps)(Home)
In Home.js component, console.log('Props', this.props)
returns {posts: []}, where I expect {posts: [{...},{...}]}.
*** EDIT:
After adding a console.log()
in the action before dispatch and in the reducer, here is the console output:
Console output link (not high enough rep to embed yet)
The redux store should be an object, but seems like it's getting initialized as an array in the root reducer. You can try the following:
const initialState = {
posts: []
}
function posts (state = initialState, action) {
switch(action.type) {
case RECEIVE_POSTS :
return Object.assign({}, state, {posts: action.posts})
default :
return state;
}
}
Then in your mapStateToProps function:
function mapStateToProps(state) {
return {
posts: state.posts
}
}