Comment Section in React Native
Tags: javascript, react, reactnative, android
Published: 2024-01-02 11:39:57

lets design a simple comment section UI in React Native. 

**Contents**
- sample data
- page structure
- design simple comment item
- add child comments data 
- form array to design child comments
- form array to design grand child comments
- margin adjustment
- the result 

**Sample Data**

Lets assume the JSON object response from the server like this

```
  {
    id: // id,
    parent_id: // parent comment id,
    name: // commenting person name,
    image: // commenting person image,
    text: // comment text,
  }
```
and the sample data like this

```
const list_comments = [
  {
    id: '1',
    parent_id: '0',
    name: 'david',
    image: '',
    text: 'this is parent cooment 1',
  },
  {
    id: '2',
    parent_id: '0',
    name: 'kumar',
    image: '',
    text: 'this is parent cooment 2',
  },
  {
    id: '3',
    parent_id: '0',
    name: 'selva',
    image: '',
    text: 'this is parent cooment 3',
  }, 
];
```
**Page structure**

Basically we have 3 main components in this page. Title, Comments List (FlatList) and Comment List Item. 

```
   const renderItem = ({ item }) => {
    return  <Text>{item.text}</Text>;
  };

  return (
    <View style={styles.container}>
      <Text style={styles.text}>Comments {listComment.length}</Text>
      <FlatList
        style={{ marginTop: 5 }}
        data={list_comments}
        renderItem={renderItem}
        keyExtractor={(item, index) => '_cmt_item' + index}
      />
    </View>
  );
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zupgiqptxb6pg9iju0ke.png)

**Design simple comment item**

With this basic structure, lets start designing the comment item component

```
. . .
const renderItem = ({ item }) => {
    return <CommentItem comment={item} />;
  };

const CommentItem = ({ comment }) => {
    return (
      <View style={styles.commentItem}>
        <ProfilePic letter={comment.name[0]} />
        <View style={{ marginLeft: 10, flex: 1 }}>
          <Text style={styles.commentBy}>{comment.name}</Text>
          <Text style={styles.commentText}>{comment.text}</Text>
        </View>
      </View>
    );
  };

 const ProfilePic = ({ letter = '' }) => {
    return (
      <View style={styles.profileImg}>
        <Text style={styles.profileText}>{letter.toUpperCase()}</Text>
      </View>
    );
  };

. . .

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipzbbqxviniwqdkdvxcm.png)

**Add child comments data**

```
const list_comments = [
 // . . .
  {
    id: '4',
    parent_id: '1',
    name: 'arul',
    image: '',
    text: 'this is c1 comment of p1',
  },
  {
    id: '5',
    parent_id: '1',
    name: 'vinoth',
    image: '',
    text: 'this is c2 comment of p1',
  },
  {
    id: '6',
    parent_id: '2',
    name: 'vishnu',
    image: '',
    text: 'this is c1 comment of p2',
  }, 
];
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpuz9bi2dgkst3fdfkjm.png)

**Form array to design child comments**

Now we need to restructure the array to render child comments below to the respective parent comment. For that, We have to <u>sort out</u> the array list in parent-child basis, then <u>add a property</u> which refers the type parent or child, that's the <u>concept</u>. Yes, We need a state variable obviously 

```
const list_comments = [{
    id: '1',
    parent_id: '0',
    name: 'david',
    image: '',
    text: 'this is parent cooment 1',
  },
. . .
 ]

export default function App() {
 const [listComment, setListComment] = useState([...list_comments]);

. . .

 React.useEffect(() => {
 // form object to render child
    var arr = [];
    var arr2 = [];
    for (let item of list_comments) {
      if (item.parent_id === '0') {
        // new property type 0 parent comment
        arr.push({ ...item, type: 0 }); 
        arr2 = list_comments.filter((ele) => ele.parent_id === item.id);
        if (arr2.length) {
          // type 1 child comment
          arr2 = arr2.map((ele) => ({ ...ele, type: 1 })); 
          arr = arr.concat(arr2);
        }
      }
    }
    setListComment(arr);    
  }, []);

  return (
   . . .
      <FlatList
        style={{ marginTop: 5 }}
        data={listComment}
        renderItem={renderItem}        
        keyExtractor={(item, index) => '_cmt_item' + index}
      />
  . . .
  );

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6thac86yckui7fwm45dg.png)

Hope we understood the sorting approach. 

**Form array to design grand child comments**

With the same approach, we are going to add grand child comments below to the child comment which is already below to the parent comment. Got it right? Two iterations and two filters going to be used. The Property `type` refers parent(0), child(1) and grand child(2)

```

const list_comments = [
 . . .
  {
    id: '7',
    parent_id: '4',
    name: 'martin',
    image: '',
    text: 'this is c1 comment of p1c1',
  },
];
. . .

  React.useEffect(() => {     

    // forming object to render grand child
    var arr = [];
    var arr2 = [],
      arr3 = [];
    for (let item of list_comments) {
      if (item.parent_id === '0') {
        arr.push({ ...item, type: 0 });
        arr2 = list_comments.filter((ele) => ele.parent_id === item.id);
        if (arr2.length) {
          for (let item2 of arr2) {
            arr3 = list_comments.filter((ele) => ele.parent_id === item2.id);
            if (arr3.length) {
              arr.push({ ...item2, type: 1 });
              arr3 = arr3.map((ele) => ({ ...ele, type: 2 }));
              arr = arr.concat(arr3);
            } else {
              arr.push({ ...item2, type: 1 });
            }
          }
        }
      }
    }
    setListComment(arr);
  }, []);

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0rfohwt7roo36xmv58f.png)

**Margin Adjustment**

Margin adjustments like marginLeft and marginTop will give the proper comment section look. 

Parent comment has more gap on top than the child comments. Also the grand child comment left side gap is 2 times bigger than the parent. 

```
const comment_margin_left = 15;
export default function App() {
. . .

  const CommentItem = ({ comment }) => {
    return (
      <View
        style={[
          styles.commentItem,
          {
            marginLeft: comment.type * comment_margin_left,
            marginTop: comment.type === 0 ? 10 : 2,
          },
        ]}>
        <ProfilePic letter={comment.name[0]} />
        <View style={{ marginLeft: 10, flex: 1 }}>
          <Text style={styles.commentBy}>{comment.name}</Text>
          <Text style={styles.commentText}>{comment.text}</Text>
        </View>
      </View>
    );
  };

. . .
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q10z8c4pfmxi1nc9xsi6.png)

Hope now you got it, why we used property type 0, 1, 2

**The Result**

After adding some mock data , the comment section page


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxn2yah9avze3u9z5k46.png)

Yeah, that's it. We are done!

Full source code [available here](https://gist.github.com/RaguRam1991/ada6d6e69fda0c52fbd5ea965556db08)

Thank you for reading this. 

Thanks Everyone, thank you for everything and Thank you DEV.TO community