Reputation: 55
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)
Upvotes: 0
Views: 2116
Reputation: 101
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
}
}
Upvotes: 5