2

I'm trying to show a list of articles in my component and I'm getting "Cannot read property 'map' of undefined" error on my "articleList.js" component .what's wrong with my code ? and also When I log articles , It's undefined.

I have below Code in my reducer :

 const initialState = {
  articles: [],
  loading: false,
  error: null
  };


export default (state=initialState, action) => {
switch (action.type) {
    case GET_ARTICLES:
      return {
         ...state,
         articles: action.payload,
         loading: false
     };

code for action :

 export const getArticles =()=> dispatch =>{
 fetch('http://localhost:8000/api/articles/')
.then(handleErrors)
.then(res => dispatch(
    {
        type : GET_ARTICLES,
        payload: res.json
    }
))}

code for component :

 componentDidMount() {
     this.props.getArticles();
 }

render() {
    const { articles } = this.props.article;

return (
  <div>
    <div>
      <div>
        {articles.map(({ id, header }) => (
          <div key={id} timeout={500} className="fade">
            <div>
              <button className="remove-btn" onClick={this.onDeleteClick.bind(this, id)} >Remove</button>
              {header}
            </div>
          </div>
        ))}
      </div>
    </div>
  </div>
);
}
}

   const mapStateToProps = state => ({
        article: state.article
    });

   export default connect(
        mapStateToProps, { getArticles} )(ArticleList);

Sorry about the large amount of code dumped, its just all related and I believe the error lies somewhere within having an undefined initialState but I cant see what I have missed defining

4
  • your reducer saves the state inside articles, your payload reads it from article and your statemapper gets it from article, so which one is correct now? And your render gets it from this.props.article.articles? How is your data looking? Commented Nov 24, 2018 at 6:55
  • I have a combine reducer 'export default combineReducers({ article : articleReducer' }) and article is singular here. Commented Nov 24, 2018 at 6:56
  • You are however never checking if articles would be undefined (as you get it from a service, it will take a while to return, your component might have rendered already), so make sure you don't render while loading (or that you at least verify if articles is not undefined). Also your fetch, shouldn't it be res.json() instead of just res.json or is the handleErrors before that doing something we don't see? :) Commented Nov 24, 2018 at 6:58
  • Thank you I will check those points in a moment. Commented Nov 24, 2018 at 7:03

2 Answers 2

1

Seems yo confuse yourself with singular / plural variables' names. Your action sets articles as plural in reducers' state:

return {
  ...state,
  articles: action.payload,

So when you mapStateToProps:

 const mapStateToProps = state => ({
      article: state.article
  });

state.article will be undefined as reducer never sets it as singular variable. Also from the snippet you provided I see no reason to use singular term anyway.

So try changing like:

  const { articles } = this.props.articles;

  const mapStateToProps = state => ({
    articles: state.articles
  });
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you , I made all articles plural and now it shows the initial state but when it wants to get data from service it shows "TypeError: articles.map is not a function" error
Because they come from an async call, you also need to check if they already exist - {articles && articles.map(...
0

Well , i think you just need to check if your articles is undefined , the state update may be asynchronous, so at the first time the render method was called it was undefined , just do something like

{articles ? {articles.map(({ id, header }) => (
      <div key={id} timeout={500} className="fade">
        <div>
          <button className="remove-btn" onClick={this.onDeleteClick.bind(this, id)} >Remove</button>
          {header}
        </div>
      </div>
    ))} : null }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.