0

I have the following regex components:

const CommentBox = React.createClass({
    render: function() {
    return (
      <div className="commentBox">
        <h1>Comments</h1>
        <CommentList comments={this.props.comments}/>
        <CommentForm />
      </div>
    );
  }
});

var CommentList = React.createClass({
    render: function() {

    return  <div className="commentList">
        {this.props.comments.toList().map(comment =>
         <Comment author={comment.author} key={comment.id}>
          {comment.text}
        </Comment>
      )}
      </div>   
  }
});

The data in this.props.comments is as follows:

{"comments":{"3":{"id":3,"author":"Me","text":"This is one comment!"},"4":{"id":4,"author":"You","text":"This is one more comment!"},"5":{"id":5,"author":"Bar","text":"This is one comment!"},"6":{"id":6,"author":"Foo","text":"This is one more comment!"},"7":{"id":7,"author":"Baz","text":"This is one comment!"},"8":{"id":8,"author":"Boo","text":"This is one more comment!"}}}

Please note that this.props.comments is an immutable.Map.

How do I map the values in the immutable.Map this.props.comments without converting its values to a List first via (toList) where I instead simply iterate over the values.

UPDATE:

I get an error saying that comment.get is undefined when I try:

const CommentList = ({comments}) => 
    <div className="commentList">
        {comments.map(comment => 
            <Comment author={comment.get('author')} key={comment.get('id')}>
                {comment.text}
            </Comment>)}
    </div> 

However the following code works as expected:

const CommentList = ({comments}) => 
    <div className="commentList">
        {comments.valueSeq().map( (comment) =>
            <Comment author={comment.author} key={comment.id}>
                {comment.text}
            </Comment>
        )}
    </div>

Why is that?

Baz
  • 12,713
  • 38
  • 145
  • 268

1 Answers1

1

Immutable.Map objects have map functions by default. You can iterate through it just like you would iterate through an immutable list. The only caveat is that the result would be a Map with the same keys of that of the iterated element, but still their corresponding values will be what we return from the map() callback function. Since Map doesn't have deep conversion of objects, I suggest using fromJS(). Please checkout this thread here: Difference between fromJS and Map.

You can try the below code:

const comments = fromJS({
 "3":{"id":3,"author":"Me","text":"This is one comment!"},
 "4":{"id":4,"author":"You","text":"This is one more comment!"},
 "5":{"id":5,"author":"Bar","text":"This is one comment!"},
 "6":{"id":6,"author":"Foo","text":"This is one more comment!"},
 "7":{"id":7,"author":"Baz","text":"This is one comment!"},
 "8":{"id":8,"author":"Boo","text":"This is one more comment!"}
})

comments.map(comment =>
         <Comment author={comment.get('author')} key={comment.get('id')} >
            {comment.get('text')}
        </Comment>);
Community
  • 1
  • 1
Samu
  • 1,448
  • 10
  • 14
  • It is because when you create the object using Immutable.Map it is taking only the first level as immutable object. So, comments.get("3") will give an object {"id":3,"author":"Me","text":"This is one comment!"}. But that object returned is on second level and It is not immutable. So, immutable functions like set(), get() etc. are not available for them. – Samu Aug 31 '16 at 12:11
  • const comments = fromJS({ "3":Map({"id":3,"author":"Me","text":"This is one comment!"}), "4":Map({"id":4,"author":"You","text":"This is one more comment!"}), "5":Map({"id":5,"author":"Bar","text":"This is one comment!"}), .... }) The above would work fine for you, but it is tiresome to a Map for all values in the second level. That's where Immutable.fromJS() comes in handy. It does the deep conversion in one go. Please check my previous example where I have used fromJS while creating the object instead of Map. – Samu Aug 31 '16 at 12:16