Go민보다 Go

프론트엔드 개발자

Update

[작성중]Storybook과 compound components와 error...

SleepingOff 2023. 12. 13. 14:48

게시글의 이미지를 보여주는 컴포넌트 내부에서 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: [''],
};

잘 되다가 커밋 하니까 나오는 오류

이미지를 추가할 때 이렇게 한 번씩 나오는 오류

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

Multi Image에서 나오는 오류

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 = [''];

 

 

728x90

'Update' 카테고리의 다른 글

[코테] 문자열 압축하는 방법  (0) 2024.01.22
깃허브로 스터디 진행하기  (0) 2024.01.12
함수 추상화 연습하기 - 계산과 액션  (1) 2023.12.08