#05 리액트를 사용한 팬레터 웹사이트 개발 : 상세화면 UI 구현 및 공통 컴포넌트 & 공통 함수 적용

728x90
반응형

      #04 리액트를 사용한 팬레터 웹사이트 개발  

: 팬레터 등록 기능 구현 및 유효성 검사 , 글자수 제한 방법

 

React#04 리액트를 사용한 팬레터 웹사이트 개발 : 팬레터 등록 기능 구현 및 유효성 검사 , 글자수

#03 리액트를 사용한 팬레터 웹사이트 개발 ▼: DummyData로 리스트 UI 구현 및 클릭한 사람 데이터만 보이기 ▼ #03 리액트를 사용한 팬레터 웹사이트 개발 : DummyData로 리스트 UI 구현 및 클릭한 사람

zerotonine2da.tistory.com


개인프로젝트 (리액트 팬레터 홈페이지 만들기 ) 과제 해설

  1. 홈화면 팬레터 클릭시 상세페이지로 이동 (useNavigate 사용)
  2. 상세화면 UI 구현 
  3. 공통 컴포넌트 적용 + 조건부 스타일
  4. 공통 함수 적용
  5. 홈버튼 (Link 사용)

 

(1) 홈 화면 팬레터 클릭시 상세페이지로 이동 (useNavigate 사용)

import { useNavigate } from 'react-router-dom';

export default function LetterCard({ letter }) {
    const naviagte = useNavigate();

    return (
        <LetterWrapper onClick={() => naviagte(`/detail/${letter.id}`)}>

▶팬레터 클릭시 상세페이지로 이동 : useNaviagte() 사용

 

(2) 상세화면 UI 구현 

import Avatar from 'components/common/Avatar';
import Button from 'components/common/Button';
import React from 'react';
import { useParams } from 'react-router-dom';
import styled from 'styled-components';
import { getFormattedDate } from 'util/data';
import { Link } from 'react-router-dom';

export default function Detail({ letters }) {
    const { id } = useParams();
    //구조분해할당으로 가져옴
    const { avatar, nickname, createdAt, writedTo, content } = letters.find((letter) => letter.id === id);
    console.log(avatar);
    return (
        <Container>
            <Link to="/">
                <HomeBtn>
                    <Button text="홈으로" />
                </HomeBtn>
            </Link>
            <DetailWrapper>
                <UserInfo>
                    <AvatarAndNickName>
                        <Avatar src={avatar} size="large" />
                        <NickName>{nickname}</NickName>
                    </AvatarAndNickName>
                    <time>{getFormattedDate(createdAt)}</time>
                </UserInfo>

                <ToMember>To: {writedTo}</ToMember>
                <Content>{content}</Content>
                <BtnWrapper>
                    <Button text="수정" />
                    <Button text="삭제" />
                </BtnWrapper>
            </DetailWrapper>
        </Container>
    );
}

▶구조분해할당으로 데이터를 가져와서 사용하기

▶버튼+이미지는 공통 컴포넌트 사용

▶상세페이지로 이동 & 홈화면으로 이동 (link)

 

(3-1) 공통 컴포넌트 : 이미지 사진

[components > common > Avatar.jsx]

import React from 'react';
import styled from 'styled-components';
import defaultUser from 'assets/person.png';

export default function Avata({ src, size }) {
    return (
        <AvatarFigure>
            <img src={src ?? defaultUser} alt="아바타이미지" />
        </AvatarFigure>
    );
}
const AvatarFigure = styled.figure`
    ${(props) => {
        switch (props.size) {
            case 'large':
                return css`
                    width: 100px;
                    height: 100px;
                `;

            default:
                return css`
                    width: 50px;
                    height: 50px;
                `;
        }
    }}
 
    border-radius: 50%; /*동그라미 */
    overflow: hidden; /*이미지가 삐져나오면 안보이게 */
    & img {
        width: 100%;
        height: 100%;
        object-fit: cover; /*figure크기만큼 꽉 차게 */
        border-radius: 50%;
    }
`;

▶src = 팬레터의 아바타 > props로 받아서 사용

▶상세페이지의 사진은 더 크게 주기위해서 조건부 스타일 적용

1) props로 받아온 size를 switch문을 통해 다르게 적용

▶주의사항 : props로 받을때는 구조분해할당으로 {src}로 받아야함 ! 안그러면 위에처럼 데이터가 있는데도 안나옴

[잘못] function Avatar(src) {

[정상] function Avatar({src}) {

 

[Detial.jsx]

<AvatarAndNickName>
                        <Avatar src={avatar} size="large" />                        
</AvatarAndNickName>

▶props로 size를 "large"로 전달

 

[LetterCard.jsx]

import Avatar from './common/Avatar';
 
<LetterWrapper onClick={() => naviagte(`/detail/${letter.id}`)}>
            <UserInfo>
                <Avatar src={letter.avatar} />

▶props로 src = {letter.avatar} 전달

 

(3-2) 공통 컴포넌트 : 버튼 (팬레터 등록 / 수정 / 삭제)

[components > common > Button.jsx]

import React from 'react';
import styled from 'styled-components';

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

const BtnWrapper = styled.div`
    display: flex;
    justify-content: flex-end;
    align-items: center;
    & button {
        background-color: #e09dd3;
        color: white;
        font-size: 16px;
        padding: 6px 12px;
        cursor: pointer;
        border: none;
    }
`;

▶공통 버튼 생성 : {text}로 팬레터 등록 / 수정 / 삭제 값 받아오기

 

[AddForm.jsx]

import Button from './common/Button';
<Button text="팬레터 등록" />

 

[Detail.jsx]

import Button from './common/Button';          
               <BtnWrapper>
                    <Button text="수정" />
                    <Button text="삭제" />
                </BtnWrapper>

 

(4) 공통 함수 : 날짜 포맷 기능 

[src> util > data.js]

export const getFormattedDate = (date) =>
    new Date(date).toLocaleDateString('ko', {
        year: '2-digit',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
    });

매개변수로 date 받아와서 newData(매개변수 date) 넣기

▶ export해서 외부에서 사용

 

[LetterCard.jsx] 기존 코드

 <NickNameAndData>
                    <p>{letter.nickname}</p>
                    <time>{formattedDate}</time>
 </NickNameAndData>

 

[LetterCard.jsx] 공통함수 적용코드

                <NickNameAndData>
                    <p>{letter.nickname}</p>
                    <time>{getFormattedDate(letter.createdAt)}</time>
                </NickNameAndData>

▶매개변수 date 부분에 letter.createdAt 인자로 넣기

 

[Detail.jsx] 공통함수 적용코드 + 구조분해할당으로 데이터 가져오기

export default function Detail({ letters }) {
    const { id } = useParams();
    //구조분해할당으로 가져옴
    const { avatar, nickname, createdAt, writedTo, content } = letters.find((letter) => letter.id === id);
 
 return (
  <time>{getFormattedDate( createdAt )}</time>
)}

▶ props로 전달받은 팬레터들 (데이터)

1) useParams() : 클릭한 팬레터의 id값 알아냄

2) props로 전달받은 팬레터들 (데이터) 중에 find해서 클릭한 팬레터 데이터를 구조분해할당으로

avatar, nickname, createAt, writedTo, content 데이터 가져옴

3) createdAt : 작성일자 => 공통함수 적용코드로 사용!

 

(5) 홈 버튼 (Link 사용)

            <Link to="/">
                <HomeBtn>
                    <Button text="홈으로" />
                </HomeBtn>
            </Link>

Link로 버튼을 감싸주고 <Link to=""> 를 사용.

끝.

 

 

반응형