백엔드 부분은 생략했다. 추후 Node.js 파트에서 따로 설명할 예정이다.
본 글에선 hooks와 axios를 이용해서 좋아요 하트 아이콘을 구현하는 방법을 소개하고자 한다.
먼저 무료 아이콘 사이트에서 필요한 아이콘을 다운받자.
'heart'를 검색하면 다양한 하트 아이콘들이 나온다.
맘에 드는 걸로 빈 하트와 채워진 하트 두 가지를 골라준 후, 저장한 이미지는 src/assets 폴더 내에 저장한다.
먼저 자식 컴포넌트부터 작성하자. 구조는 컨테이너(여기선 부모 컴포넌트)에서 API 통신과 관련된 로직을 수행하고, 컴포넌트(여기선 자식 컴포넌트)는 그 결과를 props로 받아서 출력만 해주는 형태이다.
자식 Component - 하트 아이콘
import React, { useState, useEffect } from "react";
import styled from "styled-components";
import HeartImg from "../assets/heart.png";
import EmptyHeartImg from "../assets/empty-heart.png";
const Heart = styled.img`
// css
}
`;
const HeartButton = ({ like, onClick }) => {
return (
<Heart src={like?HeartImg:EmptyHeartImg} onClick={onClick} />
);
};
export default HeartButton;
부모 컴포넌트로부터 like과 onClick을 props로 받는다.
like은 유저가 좋아요를 눌렀는지를 체크하는 state이다. 만약 좋아요를 눌렀다면 채워진 하트(♥)를 띄워주고, 좋아요를 누르지 않았다면 빈 하트(♡)를 띄워준다. onClick은 부모로부터 받은 like의 상태를 바꿔주는 함수이다. 아래에서 좀 더 구체적으로 설명하도록 하겠다.
부모 Component - 하트 아이콘이 들어가는 페이지
const Post = (props) => {
const [like, setLike] = useState(false)
...
useEffect(async () => {
const fetchData = async () => {
const res = await axios.get(...)
if (res.data.type === 'liked') setLike(true)
}
fetchData()
}, []);
const toggleLike = async (e) => {
const res = await axios.post(...) // [POST] 사용자가 좋아요를 누름 -> DB 갱신
setLike(!like)
}
return (
<>
<HeartButton like={like} onClick={toggleLike}/>
...
<Detail content={content} />
</>
);
};
export default Post;
먼저 useEffect 내에서 axios를 통해 사용자가 좋아요를 눌렀는지 여부를 판단한다(판단 결과는 type이라는 변수에 담는다!). 만약 좋아요를 눌렀다면(type === 'liked') like를 true로 바꾼다.
toggleLike함수는 사용자가 좋아요를 눌렀을 때 POST 요청을 통해 DB를 갱신한 후, toggle 형태로 like의 상태를 바꾸는(false->true / true->false) 역할을 한다. 그리고 props로 자식 컴포넌트에 전달되어 click이벤트에 바인딩된다(onClick={(e)=>()} 이런 식으로 직접 정의해도 된다 ).
여기서 핵심은 부모 컴포넌트의 setState 함수를 props 형태로 자식에게 넘겨주면, 자식 컴포넌트에서 부모의 state를 조작하는 게 가능하다는 것이다! 이를 잘 기억하면 요긴하게 써먹을 수 있다. 리덕스를 사용하고 있다면 thunk로 깔끔하게 처리할 수도 있다.
다음과 같이 잘 작동하는 것을 확인할 수 있다.
또한, 서버 로그에서 좋아요 기능이 잘 수행되는 것을 확인할 수 있다.
'웹 > React.js' 카테고리의 다른 글
[React.js] API를 연동한 Pagination 구현 (4) | 2021.05.16 |
---|---|
[React.js] 라우터를 이용한 접근 제한 구현 (Access Control & Authentication) (5) | 2021.04.22 |
[React.js] 간략한 리덕스(Redux) 정리 (0) | 2021.04.20 |