0

I'm learning React and have done a fair bit of research on this. I've quickly discovered that the map() function is what I think I should be using for looping through an array.

But, my problem is all the examples in the React documentation and in the SO questions I've viewed use <ul> and <li> HTML elements to handle the output.

I'm not sure that my use case is "correct" as far as React structure is concerned, but, I want to output a <div> with some child elements each time I loop through.

Here is my static code so far:

const Comment = () => {
    return (
        <div className="commenter">
            <div className="commenter-inner">
                <div className="commenter-left">
                    <img src={chachi}/>
                    <p className="commenter-name">Scott Baio</p>
                </div>            
                <div className="commenter-comment">
                    <p>Ehhhh!! Joanie loves Chachi!!!</p>
                </div>
            </div>
        </div> 
    )
  }

This works, but now if I have additional comments I want to be able to serve up the same block of code again but with the new commenters name, image, comment content etc.

So I've now made an array to house my multiple commenters, and things aren't really working anymore.

import React, { Component } from 'react'
import fonzie from "./img/the-fonz.jpg";
import chachi from "./img/chachi.jpg";
    
const Comments = [
    {
        id: 1, 
        name: 'Hello World', 
        photo: fonzie,
        comment: 'Welcome to learning React!'
    },
    {
        id: 2, 
        name: 'Hello World', 
        photo: chachi,
        comment: 'Welcome to learning React!'
    }    
  ];


const commentEngine = props.Comments.map((comment) =>   

    <div className="commenter" key={comment.id}>
        <div className="commenter-inner">
            <div className="commenter-left">
                <img src={comment.photo}/>
                <p className="commenter-name">{comment.name}</p>
            </div>            
            <div className="commenter-comment">
                <p>{comment.comment}</p>
            </div>
        </div>
    </div> 
  );

class Comments extends Component {
    render() {
        return (
        <div className="comments-section col-md-10 offset-md-1 col-sm-12">   
            <h4>Comments</h4>
            <commentEngine />
        </div>    
        );
    }
  }



export default Comments

At this point I'm unsure how to verify if my loop is working in the first place and how to get the output properly displaying in my app.

Any help is greatly appreciated, as is insight into whether or not this is well structured or should be separate components.

Thanks!

3 Answers 3

1

It sounds like you want to re-use the Comment component with data passed by Comments. In React, this is done via props.

So, you'll want to pass the images's src, the name, and the description:

const comments = [
  {
    id: 1,
    name: "Hello World",
    photo: fonzie,
    comment: "Welcome to learning React!",
  },
  {
    id: 2,
    name: "Hello World",
    photo: chachi,
    comment: "Welcome to learning React!",
  },
];

class Comments extends Component {
  render() {
    return (
      <div className="comments-section col-md-10 offset-md-1 col-sm-12">
        <h4>Comments</h4>
        {comments.map((comment) => {
          return (
            <Comment
              key={comment.id} // https://reactjs.org/docs/lists-and-keys.html
              name={comment.name}
              imgSrc={comment.photo}
              comment={comment.comment}
            />
          );
        })}
      </div>
    );
  }
}

Notice that I've renamed the constant array Comments to comments so that the name doesn't clash with the Comments component.

Then in the Comment component, you can access these props via the argument passed to the function component:

const Comment = (props) => {
  return (
    <div className="commenter">
      <div className="commenter-inner">
        <div className="commenter-left">
          <img src={props.imgSrc} />
          <p className="commenter-name">{props.name}</p>
        </div>
        <div className="commenter-comment">
          <p>{props.comment}</p>
        </div>
      </div>
    </div>
  );
};

Additionally, we can make the code a bit less verbose by leveraging object destructuring:

class Comments extends Component {
  render() {
    return (
      <div className="comments-section col-md-10 offset-md-1 col-sm-12">
        <h4>Comments</h4>
        {comments.map(({ id, name, photo, comment }) => {
          return (
            <Comment key={id} name={name} imgSrc={photo} comment={comment} />
          );
        })}
      </div>
    );
  }
}

// ...

const Comment = ({ imgSrc, name, comment }) => {
    return (
      <div className="commenter">
        <div className="commenter-inner">
          <div className="commenter-left">
            <img src={imgSrc} />
            <p className="commenter-name">{name}</p>
          </div>
          <div className="commenter-comment">
            <p>{comment}</p>
          </div>
        </div>
      </div>
    );
  };
Sign up to request clarification or add additional context in comments.

2 Comments

thank you very much! not just for the answer but the comments and links your provided as well. Super helpful and gets me going with this issue while setting me up to re-use this way of thinking for future use cases. Can't thank you enough, have a great day!
@HisPowerLevelIsOver9000 I'm glad I could help! I'd suggest reading through the official React tutorial, it goes through the most important concepts in practice :) reactjs.org/tutorial/tutorial.html
1
const commentEngine = (comments) => {   
    return comments.map((comment)=>{
         return (
          <div className="commenter" key={comment.id}>
          <div className="commenter-inner">
            <div className="commenter-left">
                <img src={comment.photo}/>
                <p className="commenter-name">{comment.name}</p>
            </div>            
            <div className="commenter-comment">
                <p>{comment.comment}</p>
            </div>
          </div>
         </div> 
  )})

class Comments extends Component {
    render() {
        return (
        <div className="comments-section col-md-10 offset-md-1 col-sm-12">   
            <h4>Comments</h4>
            {commentEngine(props.Comment)}
        </div>    
        );


    }
  }

Now when you render Comments you need to pass the Comment props.

<Comments Comment={Comments}/>

1 Comment

Perhaps renderComments should be commentEngine or the other way around?
-1

USAGECASE

import React, { Component } from 'react'
import fonzie from "./img/the-fonz.jpg";
import chachi from "./img/chachi.jpg";
    
const Comments = [
    {
        id: 1, 
        name: 'Hello World', 
        photo: fonzie,
        comment: 'Welcome to learning React!'
    },
    {
        id: 2, 
        name: 'Hello World', 
        photo: chachi,
        comment: 'Welcome to learning React!'
    }    
  ];


const Comment = props =>
    const {comment} = props;
    <div className="commenter" key={comment.id}>
        <div className="commenter-inner">
            <div className="commenter-left">
                <img src={comment.photo}/>
                <p className="commenter-name">{comment.name}</p>
            </div>            
            <div className="commenter-comment">
                <p>{comment.comment}</p>
            </div>
        </div>
    </div> 
  );

class Comments extends Component {
    render() {
        return (
        <div className="comments-section col-md-10 offset-md-1 col-sm-12">   
            <h4>Comments</h4>
            {Comments.map((comment,index) => <Comment key={'[CUSTOM_KEY]'} props={comment}> )}
        </div>    
        );
    }
  }



export default Comments

ANSWER

  1. First of all, You can use index parameter in Array.map
  2. Secondly, if you want to use list component you can make Single Component like <Comment comment={comment}> and you can use it with Array.map
  3. And It is very good to study How to make functional component

2 Comments

Notice that the key should be set in the rendered array, so in Comments where you do .map. Also, perhaps you meant: <Comment key={comment.id} comment={comment} />
Yeah, Exactly I mean that!

Your Answer

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