3 분 소요


1. 공용 컴포넌트 만들기

1.1 아바타 이미지

홈 화면의 아바타 이미지를 공용 컴포넌트로 만들어 적용해보자.

적용 전

function LetterCard({ letter }) {
  ...

  return (
    <>
      <LetterAvatarFigure>
        <img src={letter.avatar ?? defaultUser} alt="아바타이미지" />
      </LetterAvatarFigure>

      <LetterBox>
        <LetterDate>
          <p>{letter.nickname}</p>
          <time>{formattedDate}</time>
        </LetterDate>
        <LetterButtonBox>
          <LetterContent>
            <p>{letter.content}</p>
          </LetterContent>
          <LetterButton onClick={() => navigate(`/detail/${letter.id}`)}>자세히보기</LetterButton>
        </LetterButtonBox>
      </LetterBox>
      <Hr />
    </>
  );
}


components/common/Avatar.jsx 생성

// components/common/Avatar.jsx
import defaultUser from "assets/images/user.png";
import styled from "styled-components";

export default function Avatar() {
  return (
    <LetterAvatarFigure>
      <img src={letter.avatar ?? defaultUser} alt="아바타이미지" />
    </LetterAvatarFigure>
  );
}

const LetterAvatarFigure = styled.figure`
  width: 50px;
  height: 50px;
  border-radius: 50%;
  overflow: hidden;

  & img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
  }
`;


letter.avatar만 props로 내려주자!

// components/common/Avatar.jsx
import defaultUser from "assets/images/user.png";
import styled from "styled-components";

export default function Avatar({ src }) {
  return (
    <LetterAvatarFigure>
      <img src={src ?? defaultUser} alt="아바타이미지" />
    </LetterAvatarFigure>
  );
}
const LetterAvatarFigure = styled.figure`
  width: 50px;
  height: 50px;
  border-radius: 50%;
  overflow: hidden;

  & img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
  }
`;


props로 받으면 정상적으로 아바타가 출력된다.

import Avatar from './common/Avatar';

function LetterCard({ letter }) {
  ...

  return (
    <>
     <Avatar src={letter.avatar} />

      <LetterBox>
        <LetterDate>
          <p>{letter.nickname}</p>
          <time>{formattedDate}</time>
        </LetterDate>
        <LetterButtonBox>
          <LetterContent>
            <p>{letter.content}</p>
          </LetterContent>
          <LetterButton onClick={() => navigate(`/detail/${letter.id}`)}>자세히보기</LetterButton>
        </LetterButtonBox>
      </LetterBox>
      <Hr />
    </>
  );
}


1.2 버튼

버튼도 공용 컴포넌트로 만들어 적용해보자.

적용 전

// AddForm.jsx
function AddForm({ setLetters, activeTab }) {
  ...
  return (
    <AddFormContainer>
      <AddFormTitle>편지를 작성해주세요.</AddFormTitle>
      <form onSubmit={onAddLetter}>
      ...
        <AddFormBox>
          <AddFormButton>편지 등록</AddFormButton>
        </AddFormBox>
      </form>
    </AddFormContainer>
  );
}


Button이라는 이름으로 공통 컴포넌트를 만들고 “편지 등록” 이라는 props를 내려주자.

// AddForm.jsx
import Button from './common/Button'; // import

function AddForm({ setLetters, activeTab }) {
  ...
  return (
    <AddFormContainer>
      <AddFormTitle>편지를 작성해주세요.</AddFormTitle>
      <form onSubmit={onAddLetter}>
      ...
        <Button text="편지 등록" />
      </form>
    </AddFormContainer>
  );
}


props로 받으면 정상적으로 버튼이 출력된다.

import styled from "styled-components";

export default function Button({ text }) {
  return (
    <ButtonBox>
      <button>{text}</button>
    </ButtonBox>
  );
}

const ButtonBox = styled.div`
  background-color: #1e1e1e;
  color: white;
  border-radius: 8px;
  margin: 20px 0;
  height: 35px;
  width: 100px;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
`;


아래와 같이 함수도 props로 내려 주는 것이 가능하다.

export default function Button({ text, onClick = () => {} }) {
  return (
    <ButtonBox>
      <button onClick={onClick}>{text}</button>
    </ButtonBox>
  );
}


color, size 등 스타일을 변경하고 싶으면 조건부 스타일링 적용하기!

다른 컴포넌트들도 위와 같이 버튼 컴포넌트로 변경해주자



2. 컴포넌트 사용하기

2.1 props로 내려받기

위에서 만든 공용 컴포넌트 Avatar를 아래와 같이 props로 내려받아 사용하였다.

function Detail() {
  return (
    <DetailContainer>
      <DetailBox>
        <DetailBackClick>x</DetailBackClick>
        <DetailRow>
          <Avatar src={null} />
          <p>닉네임</p>
          <time>날짜</time>
        </DetailRow>
        <DetailHr />
        <DatailContent>내용</DatailContent>
        <DetailButton>
          <button>수정</button>
          <button>삭제</button>
        </DetailButton>
      </DetailBox>
    </DetailContainer>
  );
}


2.2 props로 받아온 데이터 조건부 스타일링 적용하기

Detail 컴포넌트에서 Avatar 의 크기를 키우고싶다면 어떻게 해야할까?

Avatar 컴포넌트는 공통 컴포넌트이므로 이렇게 props를 내려주면

// Detail.jsx
<Avatar src={avatar} size="large" />


아래와 같이 props를 받아 조건부 스타일링 적용하면 Detail page에서만 아바타 이미지를 키울 수 있다!

/ Avatar.jsx
import styled, { css } from "styled-components";
import defaultUser from "assets/images/user.png";

// (1) size props 받기
export default function Avatar({ src, size }) {
  return (
    // (2) LetterAvatarFigure에 props 넘겨주기
    <LetterAvatarFigure size={size}>
      <img src={src ?? defaultUser} alt="아바타이미지" />
    </LetterAvatarFigure>
  );
}
const LetterAvatarFigure = styled.figure`
  // (3) 조건부 스타일링 적용하기
  ${(props) => {
    switch (props.size) {
      case "large":
        return css`
          width: 75px;
          height: 75px;
        `;
      default:
        return css`
          width: 50px;
          height: 50px;
        `;
    }
  }}
  border-radius: 50%;
  overflow: hidden;

  & img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
  }
`;


조건부 스타일 적용전 코드 -> 익숙해질 때까지 연습하기

// Avatar.jsx (조건부 스타일링 적용 전)
import styled from "styled-components";
import defaultUser from "assets/images/user.png";

export default function Avatar({ src }) {
  return (
    <LetterAvatarFigure>
      <img src={src ?? defaultUser} alt="아바타이미지" />
    </LetterAvatarFigure>
  );
}
const LetterAvatarFigure = styled.figure`
  width: 50px;
  height: 50px;
  border-radius: 50%;
  overflow: hidden;

  & img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
  }
`;


카테고리:

업데이트:

댓글남기기