북마크 컴포넌트를 만들고 재사용하려고 보니 그전 만들었던 북마크 컴포넌트는 내장된 함수 기능이 많아 props 설정이 복잡했고 사실상 재사용이 불가능했다. (????) 프로젝트중 컴포넌트를 전면 바꾸면서 재사용성 높은 공통 컴포넌트의 조건을 다시한 번 생각하는 시간을 가졌다.
*북마크와 연결된 칵테일의 정보를 item에 담고 칵테일들의 전체 목록인 data까지 변경하는 다소 복잡한 로직이였다.
import { useSelector, useDispatch } from 'react-redux';
import { updateBookmark } from '../../redux/slice/userInfoSlice';
import tw from 'tailwind-styled-components';
// 사용가능한 props : 아무것도 안적으면 기본값 적용됨
// -> size : 버튼 사이즈 커스텀
//item 형태
// {
// cocktailId: 2,
// name: '체리주',
// imageUrl: 'images/cocktail/cocktail2.jpg',
// isBookmarked: true
// }
const BookmarkButton = ({
item,
onClick,
setData,
data,
size = 'w-[36px] h-[60px]',
}) => {
const dispatch = useDispatch();
const isLogin = useSelector((state) => state.isLogin.isLogin);
const bookmarkHandler = (isBookmarked) => {
//북마크 클릭시 디스패치로 아이템값과 북마크달라졌다는 내용을 등록
const id = item.cocktailId;
dispatch(updateBookmark({ id, item }));
const newDate = data.map((el, idx) => {
if (idx + 1 === item.cocktailId) {
return { ...el, isBookmarked: !el.isBookmarked };
}
return el;
});
setData(newDate);
// /cocktails/{cocktail-id}/bookmark
// const handleBookmark = () => {
// fetch(`/cocktails/${item.cocktailId}/bookmark`, {
// method: 'POST',
// // 필요한 경우 헤더 등을 설정하세요.
// })
// .then((response) => {
// if (!response.ok) {
// throw new Error('Bookmarking failed.'); // 요청이 실패한 경우 에러 처리
// }
// // 요청이 성공한 경우 추가적인 작업을 수행할 수 있습니다.
// })
// .catch((error) => {
// console.error(error); // 에러 처리
// });
};
return (
<button
// onClick={onClick}
onClick={(e, item) => {
if (isLogin) {
e.stopPropagation();
bookmarkHandler(item);
} else {
alert('로그인해야 가능합니다');
}
}}
>
{item.isBookmarked ? (
<Img
src="/images/bookmark/bookmarkOn.png"
alt="활성화된 북마크"
size={size}
/>
) : (
<Img
src="/images/bookmark/bookmarkOff.png"
alt="활성화된 북마크"
size={size}
/>
)}
</button>
);
};
export default BookmarkButton;
const Img = tw.img`
${({ size }) => size}
drop-shadow-3xl
`;
수정된 북마크 컴포넌트
클릭 함수는 분리했고, 위치 조정,크기조정 할 수 있도록 만들었다.
import React from 'react';
import { useSelector } from 'react-redux';
import tw from 'tailwind-styled-components';
// 사용법
{
/* <BookmarkBtn
onClick={handleBookmarkClick}
isBookmarked={isBookmarked}
size="w-[36px] h-[60px]"
absolute="true"
top="top-0"
right="right-14"
/> */
}
export default function BookmarkBtn({
onClick,
isBookmarked,
size = 'w-[36px] h-[60px]',
absolute,
top,
right,
}) {
const isLogin = useSelector((state) => state.isLogin.isLogin);
return (
<Button
onClick={(e) => {
if (isLogin) {
e.stopPropagation();
onClick();
} else {
alert('로그인해야 가능합니다');
}
}}
absolute={absolute}
top={top}
right={right}
>
{isBookmarked ? (
<Img
src="/images/bookmark/bookmarkOn.png"
alt="활성화된 북마크"
size={size}
/>
) : (
<Img
src="/images/bookmark/bookmarkOff.png"
alt="비활성화된 북마크"
size={size}
/>
)}
</Button>
);
}
const Button = tw.button`
${({ absolute, top, right }) => (absolute ? `absolute ${top} ${right}` : '')}
focus:outline-none
`;
const Img = tw.img`
${({ size }) => size}
drop-shadow-3xl
`;

'react' 카테고리의 다른 글
| Virtual DOM (1) | 2023.09.03 |
|---|---|
| navigate 시 데이터 넘겨주기 (0) | 2023.07.13 |
| [ERROR]React Hook "useDispatch" cannot be called at the top level. (0) | 2023.04.29 |
| [React] 상태 관리 (Redux) (0) | 2023.04.24 |
| [react- redux ERROR]Expected the root reducer to be a function. Instead, received: 'undefined' (1) | 2023.04.24 |