Advertisement
Advertisement


Cannot read property 'map' of undefined


Question

I'm following the reactjs tutorial, and I keep running into an issue when
passing the value from the state of one component into another component.

The error Cannot read property 'map' of undefined' is thrown when the map function in the CommentList component is executed.

What would cause the prop to be undefined when passing from CommentBox into the CommentList?

// First component
var CommentList = React.createClass({
  render: function() {
    var commentNodes = this.props.data.map(function (comment){
      return <div><h1>{comment.author}</h1></div>;
    });
    return <div className="commentList">{commentNodes}</div>;
  }
});
// Second component    
var CommentBox = React.createClass({
   getInitialState: function(){
     return {data: []};
   },
   getComments: function(){
      $.ajax({
        url: this.props.url,
        dataType: 'json',
        success: function(data){ this.setState({data: data}) }.bind(this),
        error: function(xhr, status, err){ console.error(url, status, err.toString()) }.bind(this)
      });
   },
   componentWillMount: function(){
      this.getComments()
   },
   render: function(){
      return <div className="commentBox">{<CommentList data={this.state.data.comments}/>}</div>;
   }
});

React.renderComponent( <CommentBox url="comments.json" />, document.getElementById('content'));
2020/04/01
1
61
4/1/2020 8:31:42 AM

Accepted Answer

First of all, set more safe initial data:

getInitialState : function() {
    return {data: {comments:[]}};
},

And ensure your ajax data.

It should work if you follow above two instructions like Demo.

Updated: you can just wrap the .map block with conditional statement.

if (this.props.data) {
  var commentNodes = this.props.data.map(function (comment){
      return (
        <div>
          <h1>{comment.author}</h1>
        </div>
      );
  });
}
2014/07/12
52
7/12/2014 12:47:26 AM

I think you forgot to change

data={this.props.data}

to

data={this.state.data}

in the render function of CommentBox. I did the same mistake when I was following the tutorial. Thus the whole render function should look like

render: function() {
  return (
    <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.state.data} />
      <CommentForm />
    </div>
  );
}

instead of

render: function() {
  return (
    <div className="commentBox">
      <h1>Comments</h1>
      <CommentList data={this.props.data} />
      <CommentForm />
    </div>
  );
2015/10/11

You need to put the data before render

Should be like this:

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];

React.render(
  <CommentBox data={data}/>,
  document.getElementById('content')
);

Instead of this:

React.render(
  <CommentBox data={data}/>,
  document.getElementById('content')
);

var data = [
  {author: "Pete Hunt", text: "This is one comment"},
  {author: "Jordan Walke", text: "This is *another* comment"}
];
2015/12/15

The error "Cannot read property 'map' of undefined" will be encountered if there is an error in the "this.props.data" or there is no props.data array.

Better put condition to check the the array like

if(this.props.data){
this.props.data.map(........)
.....
}
2019/02/27

I considered giving a comment under the answer by taggon to this very question, but well, i felt it owed more explanation for those interested in details.

Uncaught TypeError: Cannot read property 'value' of undefined is strictly a JavaScript error.
(Note that value can be anything, but for this question value is 'map')

It's critical to understand that point, just so you avoid endless debugging cycles.
This error is common especially if just starting out in JavaScript (and it's libraries/frameworks).
For React, this has a lot to do with understanding the component lifecycle methods.

// Follow this example to get the context
// Ignore any complexity, focus on how 'props' are passed down to children

import React, { useEffect } from 'react'

// Main component
const ShowList = () => {
  // Similar to componentDidMount and componentDidUpdate
  useEffect(() => {// dispatch call to fetch items, populate the redux-store})

  return <div><MyItems items={movies} /></div>
}

// other component
const MyItems = props =>
  <ul>
    {props.items.map((item, i) => <li key={i}>item</li>)}
  </ul>


/**
  The above code should work fine, except for one problem.
  When compiling <ShowList/>,
  React-DOM renders <MyItems> before useEffect (or componentDid...) is called.
  And since `items={movies}`, 'props.items' is 'undefined' at that point.
  Thus the error message 'Cannot read property map of undefined'
 */

As a way to tackle this problem, @taggon gave a solution (see first anwser or link).

Solution: Set an initial/default value.
In our example, we can avoid items being 'undefined' by declaring a default value of an empty array.

Why? This allows React-DOM to render an empty list initially.
And when the useEffect or componentDid... method is executed, the component is re-rendered with a populated list of items.

// Let's update our 'other' component
// destructure the `items` and initialize it as an array

const MyItems = ({items = []}) =>
  <ul>
    {items.map((item, i) => <li key={i}>item</li>)}
  </ul>
2019/11/04

The error occur mainly becuase the array isnt found. Just check if you have mapped to the correct array. Check the array name or declaration.

2020/04/15