메인 컴포넌트 구성
이번에는 Feed.js 와 그 하위 컴포넌트인 Comment.js, CommentHeart.js, InputCommentLine.js 를 보겠습니다 ~!
Feed.js
import React from 'react';
import Comment from './Comment';
import Member from './Member';
import InputCommentLine from './InputCommentLine';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faHeart,
faComment,
faPaperPlane,
faBookmark,
} from '@fortawesome/free-regular-svg-icons';
const Feed = ({ commentBox, setCommentBox, feeddata }) => {
return (
<>
{feeddata.map((el, idx) => {
return (
<article className="feed" key={el.id}>
<div className="feedBox">
<Member
id={el.name}
class="profile"
name={el.koreanName}
image="images/sangwon/pic1.jpg"
/>
</div>
<img src={el.feedImg} className="feedImage" alt="feed" />
<div className="buttonLine">
<div className="leftButton">
<FontAwesomeIcon className="buttons" icon={faHeart} size="xl" />
<FontAwesomeIcon
className="buttons"
icon={faComment}
size="xl"
/>
<FontAwesomeIcon
className="buttons"
icon={faPaperPlane}
size="xl"
/>
</div>
<FontAwesomeIcon
className="buttons"
icon={faBookmark}
size="xl"
/>
</div>
<div className="heartLine">
<img
className="likeProfile"
src="images/sangwon/pic1.jpg"
alt="profile"
/>
<span className="text">
<b>hasang0.0</b>님 외 <b>{el.likeCount}명</b>이 좋아합니다
</span>
</div>
<div className="contentLine">
<span className="id">hasang0.0</span>
<span>
{el.content}
<a href="#" className="type3">
...더 보기
</a>
</span>
<Comment feedNum={idx} commentBox={commentBox} />
<span className="time">42분 전</span>
</div>
<InputCommentLine
commentBox={commentBox}
setCommentBox={setCommentBox}
idx={idx}
/>
</article>
);
})}
</>
);
};
export default Feed;
일단 Feed.js 자체가 FeedData 목업 데이터에 대해서 map 하여 반복됩니다.
Feed들을 가지고 있는 Feeds.js 컴포넌트 역시 만들껄 그랬습니다.
Comment, InputComment, Member 컴포넌트를 하위 컴포넌트로 가지고 있습니다.
Comment.js
import { React } from 'react';
import CommentHeart from './CommentHeart';
const Comment = ({ feedNum, commentBox }) => {
return (
<div className="commentSection">
{commentBox[feedNum].map(el => {
return (
<div key={el.id}>
<span className="id">{el.name}</span>
{el.comment}
<div className="commentImage">
<CommentHeart />
</div>
</div>
);
})}
</div>
);
};
export default Comment;
CommentBox는 {아이디, 댓글} 로 이루어진 객체들을 가지고 있는 배열. 들을 여러개 가지고 있는 배열 구조로 되어있습니다
[
[
{ "id": 0, "name": "niceman", "comment": "nice" },
{ "id": 1, "name": "goodgirl", "comment": "good" },
{ "id": 2, "name": "greatboss", "comment": "great" },
{ "id": 3, "name": "verywoman", "comment": "verynice" }
],
[
{ "id": 0, "name": "hasang0.0", "comment": "wowow" },
{ "id": 1, "name": "thisloop", "comment": "hoho" }
],
[
{ "id": 0, "name": "hasang0.0", "comment": "wowow" },
{ "id": 1, "name": "thisloop", "comment": "hoho" }
]
]
이렇게요. 그래서 map의 index를 받아와서 그걸로 몇 번째 피드인지 확인하고,
그 배열을 map해서 이미 달려있는 댓글을 나타나게 했습니다 !!!
CommentHeart.js
import { React, useState } from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faHeart } from '@fortawesome/free-regular-svg-icons';
import { faHeart as faSolidHeart } from '@fortawesome/free-solid-svg-icons';
const CommentHeart = () => {
const [heartClass, setHeartClass] = useState('heartUnclicked');
const handleHeartClass = () => {
heartClass === 'heartUnclicked'
? setHeartClass('heartClicked')
: setHeartClass('heartUnclicked');
};
return (
<FontAwesomeIcon
className={heartClass}
icon={heartClass === 'heartUnclicked' ? faHeart : faSolidHeart}
onClick={handleHeartClass}
/>
);
};
export default CommentHeart;
댓글마다 좋아요 기능입니다. 처음에 부모 컴포넌트에서 State를 선언하고 하트를 클릭했더니,
모든 하트가 색이 바뀌는 일이 일어나서 하위 컴포넌트에서 State를 만들어서 관리하게 했습니다.
하지만 이렇게 하면 좋아요 기능 관련해서 추가 기능을 만들게 된다면 매우 불편합니다
다음엔 댓글 객체에 좋아요 클릭 여부를 넣고, setState로 객체 배열을 순회하며 아이디를 검색해서,
클릭한 객체의 좋아요 클릭 여부 값을 변경하는 방식을 보여드리겠습니다 후후
InputCommentHeart.js
import { React, useState } from 'react';
const InputCommentLine = ({ setCommentBox, idx }) => {
const [commentValue, setCommentValue] = useState('');
const onChange = e => {
setCommentValue(e.target.value);
};
const onSubmit = e => {
e.preventDefault();
if (commentValue === '') return;
setCommentBox(value =>
value.map((comments, index) => {
return index === idx
? [...comments, { name: 'hasang0.0', comment: commentValue }]
: comments;
})
);
setCommentValue('');
};
return (
<form className="commentLine" onSubmit={onSubmit}>
<input
type="text"
placeholder="댓글 달기..."
className="comment"
value={commentValue}
onChange={onChange}
/>
<input type="submit" value="게시" className="submit" />
</form>
);
};
export default InputCommentLine;
대망의 마지막 댓글 달기 컴포넌트입니다 ~!
댓글을 저장하는 곳이 다른 컴포넌트에 있어서 props로 setCommentBox를 가져왔습니다.
그리고 현재 댓글달 때(inputComment) 댓글이 달릴 곳(Comment)이 같은 피드(index===idx)이도록
비교할 수 있게 idx도 가져왔습니다.
위에서 말했던 것처럼 객체 배열로 이루어진 State를 수정하기 위해서 set 안에 변수를 만들고,
그 변수를 map해서 조건이 맞을 시 ! spread 연산자를 사용하여,
현재까지 있던 댓글 + 추가 된 댓글로 CommentBox가 바뀔 수 있게 만들었습니다 ~!
그리고 마지막은 댓글창을 비워주기 위해 빈 값으로 설정
이상으로 위스타그램 프로젝트였습니다.
React의 컴포넌트와 프롭스 개념이 미흡한 상태로 프로젝트를 시작해서,
전체적인 코드가 난잡해보입니다. 시작할 때 기획을 확실히 하고 코드를 작성하는 요령이 필요해보입니다
감사합니다 ~!
'Project' 카테고리의 다른 글
Wish Korea 프로젝트 (Lush 클론 코딩) - 상세 페이지 (0) | 2022.07.03 |
---|---|
westagram project(인스타그램 클론 코딩) - 메인 화면 (1) (2) | 2022.07.03 |
westagram project(인스타그램 클론 코딩) - 로그인 (2) | 2022.06.26 |
댓글