[React] 댓글 리스트 구현하기 : props 활용

November·2024년 12월 31일
post-thumbnail

댓글 컴포넌트

Comment.js

function Comment() {
     return (
        <div>
            {/* 작성한 사람의 이미지 */}
            <div>
                <img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png" />
            </div>

            {/* 작성한 사람의 이름과 댓글 내용 */}
            <div>
                <span>작성자 이름</span>
                <span>댓글 내용</span>
            </div>
        </div>
    );
}

export default Comment;

댓글리스트 컴포넌트

CommentList.js

import Comment from "./Comment";

function CommentList() {
    return (
        <>
            <Comment />
            <Comment />
            <Comment />
        </>
    );
}
export default CommentList;

App.js 파일에 CommentList 컴포넌트를 추가

import CommentList from "./comment/CommentList";

function App() {
  return (
    <>
      <CommentList />
    </>
  );
}
export default App;

⬇️⬇️ 결과! ⬇️⬇️

Comment 컴포넌트에 props 변수로 전달된 값을 출력하도록 변경하기

⭐️⭐️ props ⭐️⭐️

  • 컴포넌트의 속성을 설정할 때 사용
  • props는 해당 컴포넌트를 사용하는 부모 컴포넌트에서 설정
function Comment(props) {}

컴포넌트 매개변수에 props를 전달하고

   <div style={styles.contentContainer}>
   		<span style={styles.nameText}>{props.name}</span>
   		<span style={styles.commentText}>{props.comment}</span>
   </div>

props 변수로 전달된 값으로 변경해주기

CommentList 컴포넌트에 props 값을 설정해서 Comment 컴포넌트를 호출하도록 수정

import Comment from "./Comment";

function CommentList() {
    return (
        <>
            <Comment name="홍길동" comment="동쪽에 살아요." />
            <Comment name="홍길남" comment="남쪽에 살아요." />
            <Comment name="고길동" comment="둘리가 싫어요." />
        </>
    );
}
export default CommentList;

⬇️⬇️ 결과! ⬇️⬇️
(스타일은 따로 적용해 주었습니다)

댓글 데이터 이용하기

CommentList.js 파일에 댓글 데이터를 추가

const comments = [
    { name: "홍길동", comment: "동쪽에 살아요." },
    { name: "홍길남", comment: "남쪽에 살아요." },
    { name: "고길동", comment: "둘리가 싫어요." }
];

댓글 데이터를 이용해서 Comment가 출력되도록 수정하기

똑같은 컴포넌트가 반복되어서 나올 때는 키값이 필요함 key={i}

function CommentList() {
    return (
        <>
            {   // 익명 함수 표현식
                comments.map(function (c, i) {
                    return <Comment key={i} name={c.name} comment={c.comment} />;
                })
            }

            {   // 화살표 함수 축약
                comments.map((c, i) => <Comment key={i} name={c.name} comment={c.comment} />)
            }
        </>
    );
}
export default CommentList;

글쓴이 별로 이미지를 다르게 출력하기

데이터 구조

const comments = [
    { name: "홍길동", comment: "동쪽에 살아요.", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg" },
    { name: "홍길남", comment: "남쪽에 살아요.", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
    { name: "고길동", comment: "둘리가 싫어요.", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" }
];

CommentList.js에 picture={c.picture} 추가

{  
comments.map((c, i) => 
           <Comment key={i} name={c.name} comment={c.comment} picture={c.picture} 
}

Comment 컴포넌트에 props 변수로 전달된 이미지를 사용하도록 수정

<div>
	<img style={styles.image} src={props.picture} />
</div>

특정유저만 출력되도록 해보기

"홍길동"만 출력해보기

function CommentList() {
    return (
        <>
            <h1>홍길동만 출력</h1>
            {   // filter 메서드
                comments
                    .filter(c => c.name === "홍길동")
                    .map((c, i) => <Comment key={i} name={c.name} comment={c.comment} picture={c.picture} />)
            }
            {   // && 연산자를 이용한 조건부 렌더링
                comments
                    .map((c, i) => c.name === "홍길동" && <Comment key={i} name={c.name} comment={c.comment} picture={c.picture} />)
            }
            {   // 삼항연산자를 이용
                comments
                    .map((c, i) => c.name === "홍길동" ? <Comment key={i} name={c.name} comment={c.comment} picture={c.picture} /> : null)
            }
        </>
    );
}
export default CommentList;

댓글 정보와 사용자 정보가 분리되어 있는 경우

데이터 구조

const users = [
    { name: "홍길동", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg" },
    { name: "홍길남", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
    { name: "고길동", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" }
];


const comments = [
    { name: "홍길동", comment: "동쪽에 살아요." },
    { name: "홍길남", comment: "남쪽에 살아요." },
    { name: "고길동", comment: "둘리가 싫어요." }
];

getUserPicture 함수 생성

  • filter 함수를 이용해 매개변수 name과 users 데이터에서 받아온 user의 name이 일치하는 것 필터링
  • 0번째 인덱스의 picture 가져오기
function getUserPicture(name) {
    return users.filter(user => user.name === name)[0].picture;
}

CommentList에서 사진을 받아올 때 getUserPicture 함수 이용

function CommentList() {
    return (
        <>
            {
                comments.map((c, i) => <Comment key={i} name={c.name} comment={c.comment} picture={getUserPicture(c.name)} />)
            }
        </>
    );
}
export default CommentList;

find 함수 이용하는 방법

find() 는 처음으로 일치하는 배열 요소를 반환하기 때문에 배열 인덱스를 사용할 필요가 없다.

picture={users.find(user => user.name === c.name).picture} 

댓글 정보와 사용자 정보를 결합한 새로운 데이터를 정의

comments 데이터를 map()으로 돌면서 객체 복사, picture 라는 새로운 항목 추가
users 데이터에서 find() 이용해서 users의 name과 comments의 name이 일치하는 것의 picture를 가져옴

const commentsWithPicture = comments.map(c => ({ ...c, picture: users.find(u => u.name === c.name).picture }));

사용자 데이터에 주민번호가 전달되었을 때, 남, 여 구분을 이름 뒤에 출력하도록

예) 홍길동 (남)

데이터 구조

const users = [
   { name: "홍길동", regno: "701010-1457934", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg" },
   { name: "홍길남", regno: "201010-3457934", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
   { name: "고길동", regno: "211010-4157934", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" }
];


const comments = [
   { name: "홍길동", comment: "동쪽에 살아요." },
   { name: "홍길남", comment: "남쪽에 살아요." },
   { name: "고길동", comment: "둘리가 싫어요." }
];

getUserGender 함수 생성

[1, 3].includes(Number(regno[7])) ? "남" : "여";

  • 배열 [1,3]에 중 포함하는게 있으면 "남" 아니면 "여"
  • regno[7] : 7번째 인덱스가 주민번호 뒷자리 성별 구분하는 숫자
  • 문자열이기 때문에 Number()로 자료형 변환
function getUserGender(name) {
    const regno = users.find(u => u.name === name).regno;
    return [1, 3].includes(Number(regno[7])) ? "남" : "여";
}
//유저데이터에서 받아온 u의 name과 매개변수로 받은 name이 일치하는 것의 regno를 가져옴 

const commentsWithPicture = comments.map(c => ({
    ...c, //댓글 객체를 map()으로 돌면서 복사 
    picture: users.find(u => u.name === c.name).picture,
  //이름 변수 뒤에 getUserGender함수 이용해서 성별 출력
    name: `${c.name} (${getUserGender(c.name)})`
}));

CommentList 내부

 {
commentsWithPicture.map((c, i) => <Comment key={i} name={c.name} comment={c.comment} picture={c.picture} />)
}

0개의 댓글