질문:
아래의 코드에서 description 을 적용할지 고민중인데요. 만약에 적용하려면 어떻게 하면 될까요? 기타 프롭스처럼 설정해도 되는지요? 문제는 모든 아이템들이 description 가 있는건 아니니깐요.
import type { BookData } from "@/types";
import Link from "next/link";
import style from "./book-item.module.css";
export default function BookItem({
id,
title,
subTitle,
description,
author,
publisher,
coverImgUrl
}: BookData) {
return (
<Link href={/book/${id}} className={style.container}>
<img src={coverImgUrl} />
<div>
<div className={style.title}>{title}</div>
<div className={style.subTitle}>{subTitle}</div>
<br />
<div className={style.author}>{author} | {publisher}</div>
</div>
</Link>
);
}
응답:
다른 프롭스처럼 추가하면 되지만, 모든 아이템이 description을 가지지 않을 수 있기 때문에 이를 고려하여 조건부 렌더링을 해야 합니다.
description 적용 방법:
- 기존 프롭스처럼 설정
BookItem 컴포넌트에서 description을 받도록 추가합니다. - 조건부 렌더링
description이 존재하는 경우에만 표시하도록 합니다. - 스타일 고려
description의 길이가 길어질 가능성이 있으므로 적절한 CSS 처리가 필요합니다.
수정후 코드
import type { BookData } from "@/types";
import Link from "next/link";
import style from "./book-item.module.css";
export default function BookItem({
id,
title,
subTitle,
description, // ✅ 추가
author,
publisher,
coverImgUrl
}: BookData) {
return (
<Link href={`/book/${id}`} className={style.container}>
<img src={coverImgUrl} alt={title} />
<div>
<div className={style.title}>{title}</div>
<div className={style.subTitle}>{subTitle}</div>
{/* ✅ description이 있을 때만 렌더링 */}
{description && <p className={style.description}>{description}</p>}
<div className={style.author}>{author} | {publisher}</div>
</div>
</Link>
);
}
스타일 (book-item.module.css)
.description {
font-size: 14px;
color: #555;
margin-top: 8px;
line-height: 1.5;
max-height: 3em; /* 3줄까지만 표시 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
설명:
- max-height: 3em → 3줄까지만 표시
- overflow: hidden → 넘치는 부분 숨김
- text-overflow: ellipsis → 말줄임(...) 표시
- white-space: nowrap → 한 줄로 유지하려면 사용 (여러 줄 허용하려면 제거)
정리
- description을 조건부 렌더링하여 데이터가 없는 경우 UI가 깨지지 않도록 처리
- CSS 스타일을 추가하여 설명이 너무 길어도 UI가 정돈되도록 설정
- UX를 고려하여 3줄까지만 표시하고 말줄임(...) 처리
질문:
여기서 추가된 부분 " {description && <p className={style.description}>{description}</p>}" 코드내용을 설명해 주세요.
응답:
{description && <p className={style.description}>{description}</p>} 코드 설명
이 코드는 **조건부 렌더링(Conditional Rendering)**을 활용하여, description이 존재할 때만 <p> 태그를 렌더링하는 방식입니다.
1. 조건부 렌더링이란?
- React에서 특정 조건이 true일 때만 컴포넌트 또는 JSX 요소를 렌더링하는 기법입니다.
- 여기서는 description이 Truthy한 값일 때만 <p> 태그가 생성됩니다.
2. && 연산자의 동작 원리
{description && <p className={style.description}>{description}</p>}
이 표현식은 **JavaScript의 논리 AND 연산자(&&)**를 활용한 조건부 렌더링 방식입니다.
동작 방식:
- description 값이 존재하면 (Truthy)
→ <p className={style.description}>{description}</p>가 렌더링됩니다. - description 값이 없으면 (Falsy)
→ 아무것도 렌더링되지 않습니다.
3. Truthy와 Falsy 값
JavaScript에서 다음과 같은 값들은 **Falsy(거짓 같은 값)**로 간주됩니다:
false, 0, "", null, undefined, NaN
즉, description이 **null, undefined, "" (빈 문자열)**일 경우 JSX 요소가 렌더링되지 않습니다.
예제1: description이 존재하는 경우
const description = "이 책은 프론트엔드 개발에 관한 내용을 다룹니다.";
{description && <p>{description}</p>}
// 결과: <p>이 책은 프론트엔드 개발에 관한 내용을 다룹니다.</p>
예제2: description이 없는 경우
const description = ""; // 혹은 null 또는 undefined
{description && <p>{description}</p>}
// 결과: 아무것도 렌더링되지 않음
4. 일반적인 if 문과의 차이점
기존의 if 문을 사용한 방식:
if (description) {
return <p>{description}</p>;
} else {
return null;
}
→ JSX 내에서 if 문을 직접 사용할 수 없어서 JSX 외부에서 조건문을 사용해야 함
→ 코드가 길어지고 가독성이 떨어짐
&& 연산자를 사용하면 더 간결하게 작성 가능!
{description && <p>{description}</p>}
5. 추가로 고려할 사항
- description이 숫자(0)일 경우에도 Falsy로 평가되므로, 숫자를 표시하려면 description !== undefined같은 추가적인 조건이 필요할 수 있습니다.
- 만약 description이 null이거나 undefined일 때 대체 문구를 보여주고 싶다면, ||(OR) 연산자를 사용할 수 있습니다.
대체 문구를 추가하는 방법
<p>{description || "설명이 없습니다."}</p>
→ description이 없을 경우 "설명이 없습니다."가 출력
결론:
{description && <p className={style.description}>{description}</p>}
description이 존재할 때만 <p> 태그를 렌더링하여 불필요한 공백을 방지
&& 연산자를 활용하여 가독성이 좋고 간결한 코드 작성
Falsy 값(null, undefined, "", 0 등)은 자동으로 처리됨.
https://www.udemy.com/course/onebite-next
'Next.js' 카테고리의 다른 글
Next.js 프로젝트 생성 (0) | 2025.03.16 |
---|---|
Warning: React Hook useEffect has a missing dependency: 'setData'. Either include it or remove the dependency array. (0) | 2024.05.17 |