게시글의 이미지를 보여주는 컴포넌트 내부에서 if 문을 통해 여러 return을 하고 있습니다. 그래서 하나의 컴포넌트 안에서 조건부로 나뉘는 게 아닌 조건에 맞는 컴포넌트들로 각각 나누어 사용해보는 것으로 하였습니다. 이번에 배운 컴파운드 컴포넌트 패턴을 적용하여 Image라는 객체에 넣어 관리하려고 했습니다.
기존 코드
import styled from 'styled-components';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import imageBigIcon from '../../assets/img/image-big-icon.svg';
import deleteIcon from '../../assets/img/delete-icon.svg';
const ImagePreview = ({ imageUrls, onDeleteImage }) => {
if (!imageUrls.length) {
return (
<ImagePreviewCont>
<PreviewSpan>
오른쪽 하단 버튼을 눌러
<br />
이미지를 추가해보세요.
</PreviewSpan>
</ImagePreviewCont>
);
}
if (imageUrls.length === 1) {
return (
<ImageWrapper>
<StyledImage src={imageUrls[0]} alt="" />
<DeleteButton onClick={() => onDeleteImage(0)} />
</ImageWrapper>
);
}
return (
<Swiper spaceBetween={10} slidesPerView={1.2} pagination={{ clickable: true }}>
{imageUrls.map((url, idx) => (
<SwiperSlide key={idx}>
<ImageWrapper>
<StyledImage src={url} alt="" />
<DeleteButton aria-label="이미지 삭제 버튼" type="button" onClick={() => onDeleteImage(idx)} />
</ImageWrapper>
</SwiperSlide>
))}
</Swiper>
);
};
export default ImagePreview;
const ImagePreviewCont = styled.div`
width: 100%;
height: 204px;
border-radius: 10px;
border: 0.5px solid #dbdbdb;
background: #f4f4f4 url(${imageBigIcon}) no-repeat center 50px;
margin-bottom: 30px;
color: #c4c4c4;
text-align: center;
font-size: 12px;
line-height: 15px;
`;
const PreviewSpan = styled.span`
position: relative;
top: 124px;
`;
const ImageWrapper = styled.div`
position: relative;
width: 100%;
`;
const StyledImage = styled.img`
width: 100%;
height: 204px;
margin-bottom: 28px;
object-fit: fill;
border-radius: 10px;
border: 0.5px solid #dbdbdb;
`;
const DeleteButton = styled.button`
position: absolute;
top: 8px;
right: 8px;
background: url(${deleteIcon});
width: 22px;
height: 22px;
`;
새롭게 작성한 코드
import styled from 'styled-components';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
const DefaultImage = () => {
return(
<ImagePreviewCont>
<PreviewSpan>
오른쪽 하단 버튼을 눌러
<br />
이미지를 추가해보세요.
</PreviewSpan>
</ImagePreviewCont>
)
}
const SingleImage = ({url, onClick}) => {
return(
<ImageWrapper>
<StyledImage src={url} alt="" />
<DeleteButton aria-label="이미지 삭제 버튼" type="button" onClick={() => onClick(idx)} />
</ImageWrapper>
)
}
const MultiImage = ({imageUrls, onClick}) => {
return (
<Swiper spaceBetween={10} slidesPerView={1.2} pagination={{ clickable: true }}>
{imageUrls.map((url, idx) => (
<SwiperSlide key={idx}>
<SingleImage url={url} onClick={onClick} />
</SwiperSlide>
))}
</Swiper>
)
}
const Image = {
Default: DefaultImage,
Single: SingleImage,
Multi: MultiImage
}
export default Image;
최대한 스타일에는 변경이 없도록 하였습니다.
*백그라운드로 들어가던 icon들을 svg 파일에서 컴포넌트로 교체할 예정입니다.
새롭게 작성한 코드를 통해 스토리북에 보이도록 하려고 다음과 같은 스토리를 작성하였습니다.
스토리북 코드
import Image from '../components/card/ImageItem';
export default {
title: 'Comp/ImageItem',
component: Image,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
imageUrls: {
type: 'array',
},
onClick: onclick,
},
};
const Template = (args) => <Image.Default {...args} />;
//error: SyntaxError: Unexpected token '<'
export const Default = Template.bind({});
Default.args = {};
여기에서 에러가 나는 부분이 생겨 해결 방법을 찾고 있습니다. 에러는 코드에 주석으로 표시하였습니다.
Template을 쓰게 되면 위와 같은 에러가 계속 나서 결국 안 쓰는 방법으로 해보았습니다.
참고하기 >> https://storybook.js.org/blog/component-story-format-3-0/?ref=storybookblog.ghost.io
import Image from '../components/card/ImageItem';
export default {
title: 'Comp/ImageItem',
component: Image,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
imageUrls: {
type: 'array',
},
// onClick: onclick,
},
};
// const Template = (args) => Image.Default;
//error: SyntaxError: Unexpected token '<'
export const DefaultImage = Image.Default;
export const SingleImage = Image.Single;
SingleImage.args = {
url: '',
onclick: () => {
console.log('click');
},
};
export const MultiImage = Image.Multi;
MultiImage.args = {
imageUrls: [''],
};
잘 되다가 커밋 하니까 나오는 오류

해당 오류를 무시하고 넘어가면 이미지가 또 잘 들어갑니다...

Single Image에서 나오는 오류와 이 Multi Image에서 나오는 에러가 서로 연관이 있을지 모르겠습니다. 둘 다 undefined를 읽을 수 없다고 하는데, 이미지가 들어가면서 뭔가 잘못되는지..
현재 스토리 코드
import Image from '../components/card/ImageItem';
export default {
title: 'Comp/ImageItem',
component: Image,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
url: {
control: { type: 'file', accept: '.png' },
},
onClick: { action: 'clicked' },
},
};
// const Template = (args) => Image.Default;
//error: SyntaxError: Unexpected token '<'
export const DefaultImage = Image.Default;
export const SingleImage = Image.Single;
export const MultiImage = Image.Multi;
MultiImage.imageUrls = [''];
'Update' 카테고리의 다른 글
[코테] 문자열 압축하는 방법 (0) | 2024.01.22 |
---|---|
깃허브로 스터디 진행하기 (0) | 2024.01.12 |
함수 추상화 연습하기 - 계산과 액션 (1) | 2023.12.08 |