Jack Collins
Jack Collins

Reputation: 421

Why am I unable to access a Redux store in a child React component?

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

Answers (3)

davnicwil
davnicwil

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

sloppypasta
sloppypasta

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

sloppypasta
sloppypasta

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

Related Questions