Reputation: 421
I'm trying to understand how I can map my Redux state to a React component. I'm not quite sure what is going wrong here so I'll simply post the code and the error messages I receive.
My redux store:
const initialState = {
userPosts: [{
0: {
content: 'Test post one',
likes: 0
},
1: {
content: 'Test post two',
likes: 0
},
2: {
content: 'Test post three',
likes: 0
}
}]
}
console.log(initialState)
function likeReducer(state = initialState, action ){
switch (action.type) {
case 'LIKE':
return {
likes: state.likes + 1
};
default:
return state;
}
}
function postReducer(state = initialState, action){
switch (action.type){
case 'POST':
return{
userPosts: 'Test'
};
default:
return state;
}
}
const rootReducer = combineReducers({like: likeReducer, post: postReducer})
const store = createStore(rootReducer, applyMiddleware(logger));
const render = (Component) => {
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<Switch>
<Route exact path='/' component={Component} />
<Route path='/profile' component={Profile} />
</Switch>
</HashRouter>
</Provider>,
document.getElementById('react-app-root')
);
};
render(App);
/*eslint-disable */
if (module.hot) {
module.hot.accept('./components/App', () => {
render(App)
});
}
/*eslint-enable */
The Component I'm trying to access the store in:
import Post from './Post';
import PropTypes from "prop-types";
import { connect } from 'react-redux';
function LiveFeed(props){
console.log(props)
return(
<div className="liveFeed">
{props.userPosts.map((post, index) =>
<Post content={post.content}
likes={post.likes}
/>
)}
</div>
)
};
const mapStateToProps = (state) => ({
userPosts: state.userPosts
});
export default connect(mapStateToProps)(LiveFeed);
I am getting the follow console error:
Uncaught TypeError: Cannot read property 'map' of undefined
I've different variations of this.props.userPosts
, props.userPosts
, userPosts
etc, to no avail.
Upvotes: 2
Views: 1760
Reputation: 30957
It is connecting, it's just that your userPosts
state should actually be under state.post.userPosts
, rather than state.userPosts
- in the combineReducers
call you've specified that that posts state should go under the post
subtree.
Try amending state.userPosts
to state.post.userPosts
in mapStateToProps
and you should see it work.
Note, you'll also want to amend the structure of initialState
accordingly - you should have a like
object and a post
object in there and then only pass the relevant subtree as the initial state in the appropriate reducer:
const initialState = {
post: {
userPosts: [{
0: {
content: 'Test post one',
likes: 0
},
1: {
content: 'Test post two',
likes: 0
},
2: {
content: 'Test post three',
likes: 0
}
}]
},
like: {
likes: 0
}
}
Further note - it may be you actually want state.userPosts
to exist, if that's the case then you should rework your reducers structure - do something like
const rootReducer = combineReducers({ userPosts: postReducer, ... })
And just have postReducer
return an array of posts, rather than an object with a field userPosts
.
Upvotes: 2
Reputation: 1126
Your reducers have different state objects and should have different initialStates. In your mapStateToProps
function, add a console.log(state)
and you'll see what I mean. In that same function, you'll want to reference state.post.userPosts
.
Upvotes: 0
Reputation: 1126
You need to supply your store as the store to a Provider
from react-redux
. This can be done like:
ReactDOM.render(
<Router history={history}>
<Provider store={store}>
<Route component={App} />
</Provider>
</Router>,
document.getElementById('root')
)
https://react-redux.js.org/api/provider
Upvotes: -1