게시글 더보기, 접기 토글 버튼을 만드는 법에 대해서 알아보자!
만들 예제의 완성본
글자수가 100자 이상일때 더보기 버튼이 뜨고, 더보기 버튼을 누르면 글 전체가 펼쳐지고, 접기 버튼을 누르면 원래 접힌 상태로 돌아간다.
1. 기본적인 마크업을 한다.
Board.jsx 라는 컴포넌트를 만들고, 여기에 Board.css 파일을 import해서 style을 적용한다.
그리고 App.js 에 Board .jsx 컴포넌트를 import해서 렌더링한다.
Board.jsx
import "./Board.css";
export const Board = () => {
const content =
"동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산 대한사람 대한으로 길이 보전하세 남산위에 저 소나무 철갑을 두른듯 바람서리 불변함은 우리기상 일세 무궁화 삼천리 화려강산 대한사람 대한으로 길이보전하세 가을하늘 공활한데 높고 구름없이 밝은달은 우리가슴 일편단심일세 무궁화 삼천리 화려강산 대한사람 대한으로 길이보전하세";
return (
<div className="container">
<span className="content">{content}</span>
<div className="content-toggle"></div>
</div>
);
};
Board.css
.container {
width: 300px;
margin: 100px auto 0px auto;
}
.content {
font-size: 18px;
}
.content-toggle {
display: inline-block;
font-size: 18px;
color: gray;
}
App.js
import { Board } from "./Board";
export default function App() {
return (
<div>
<Board />
</div>
);
}
2. 조건에 따라 게시글과 버튼을 렌더링하게 만든다.
완성된 코드
(전체 코드 밑부분에 이 코드에 대한 자세한 설명이 있습니다)
Board.jsx
import { useMemo, useRef, useState } from "react";
import "./Board.css";
export const Board = () => {
const content =
"동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산 대한사람 대한으로 길이 보전하세 남산위에 저 소나무 철갑을 두른듯 바람서리 불변함은 우리기상 일세 무궁화 삼천리 화려강산 대한사람 대한으로 길이보전하세 가을하늘 공활한데 높고 구름없이 밝은달은 우리가슴 일편단심일세 무궁화 삼천리 화려강산 대한사람 대한으로 길이보전하세";
const [isShowMore, setIsShowMore] = useState(false); // 더보기 열고 닫는 스위치
const textLimit = useRef(100); // 글자수 제한 선언
// 조건에 따라 게시글을 보여주는 함수
const commenter = useMemo(() => {
const shortReview = content.slice(0, textLimit.current); // 원본에서 글자 수만큼 자른 짧은 버전
if (content.length > textLimit.current) {
// 원본이 길면 (원본 글자수 > 제한된 갯수)
if (isShowMore) {
return content; // 더보기가 true면 원본 바로 리턴
}
return shortReview; // (더보기가 false면) 짧은 버전 리턴
}
return content; // 그렇지않으면 (짧은 글에는) 쓴글 그대로 원본 리턴
}, [isShowMore]); // isShowMore의 상태가 바뀔때마다 호출됨
return (
<div className="container">
<span className="content">{commenter}</span>
<div
className="content-toggle"
onClick={() => setIsShowMore(!isShowMore)}
>
{content.length > textLimit.current &&
(isShowMore ? "[접기]" : "... [더 보기]")}
</div>
</div>
);
};
코드 순서 및 설명
(1) 초기값을 false로 설정하여 접힌 상태로 만든다.
false = 접힌 상태 → 더보기 버튼이 나타난 상태
true = 펼쳐진 상태 → 접기 버튼이 나타난 상태
const [isShowMore, setIsShowMore] = useState(false);
(2) Ref 객체 생성하기
100글자로 제한해서, 100글자가 넘으면 더보기 버튼이 생기게 만들기 위함이다.
const textLimit = useRef(100);
(3) 조건에 따라 게시글을 보여주는 commenter 라는 함수를 만든다.
const commenter = useMemo(() => {
// 조건에 따라 게시글을 보여주는 함수
const shortReview = content.slice(0, textLimit.current); // 원본에서 글자 수만큼 자른 짧은 버전
if (content.length > textLimit.current) {
// 원본이 길면 (원본 글자수 > 제한된 갯수)
if (isShowMore) {
return content; // 더보기가 true 면 원본 바로 리턴
}
return shortReview; // (더보기가 false면) 짧은 버전 리턴
}
return content; // 그렇지않으면 (짧은 글에는) 쓴글 그대로 리턴
}, [isShowMore]); // isShowMore의 상태가 바뀔때마다 호출됨
- content(원본 본문)에 slice 메서드를 써서, 원본에서 글자수가 0부터 100까지만 나오게 잘라서 shortReview에 할당한다. 즉, shortReview는 짧은 버전! ▶ const shortReview = content.slice(0, textLimit.current);
- 만약 원본의 길이가 100글자보다 길 때, ▶ if (content.length > textLimit.current) 가 true
isShowMore(접히고 펼쳐진 상태)가 true(펼쳐진상태)면, content(원본)을 return하고, ▶ return content;
isShowMore(접히고 펼쳐진 상태)가 false(접힌상태)면, showReview(짧은버전)을 return한다. ▶ return shortReview;
- 만약 원본의 길이가 100글자보다 짧을 때는, ▶ if (content.length > textLimit.current)가 false
content(원본)를 return한다. ▶ return content;
(4) 만든 comment함수를 적용한다.
함수의 조건에 따라 본문에는 원본이 나타나거나, 짧은버전이 나타나게 된다.
return (
<div className="container">
<span className="content">{commenter}</span>
</div>
);
(5) <div>를 만들어서 더보기/닫기 버튼이 조건에 따라 나오게 만든다.
<div
className="content-toggle"
>
{content.length > textLimit.current &&
(isShowMore ? "[접기]" : "... [더 보기]")}
</div>
&& 논리연산자
alert( true && true ); // true;
alert( false && true ); // false;
alert( true && false ); // false;
alert( false && false) // false;
콘텐츠의 길이와 상태에 따라 버튼을 렌더링하는 코드이다.
원본의 길이가 100글자보다 크면 ( content.length > textLimit.current 가 true), 두번째 피연산자를 평가해서 반환한다.
- isShowMore(접히고 펼쳐진 상태)가 true(펼쳐진상태)면, [접기]를 반환한다.
- isShowMore(접히고 펼쳐진 상태)가 false(접힌상태)면, ... [더 보기]를 반환한다.
원본의 길이가 100글자보다 작으면 ( content.length > textLimit.current 가 false), 두번째 피연산자 평가가 진행되지않으므로, 버튼이 표시되지 않는다.
.content-toggle {
display: inline-block;
font-size: 18px;
color: gray;
}
버튼이 표시됐을 때, 버튼의 css는 다음과 같다.
(6) 더보기/닫기에 onClick 이벤트를 달아서 toggle이 되게 만든다.
클릭할때마다 isShowMore(접히고 펼쳐진 상태)가 true(펼쳐진상태) ↔ false(접힌상태)로 왔다갔다함
<div
className="content-toggle"
onClick={() => setIsShowMore(!isShowMore)}
>
{content.length > textLimit.current &&
(isShowMore ? "[접기]" : "... [더 보기]")}
</div>
앞서 설명한 기능은 이런식으로 게시글을 만들 때 사용하면 유용하다.
'Libraries > React' 카테고리의 다른 글
[React] Filter (1) 최신순/오래된순 등등 필터링 (0) | 2023.11.08 |
---|---|
[React] 버튼을 클릭시 모달창(팝업창) 컴포넌트 뜨게 하기, 닫기(취소) 버튼 누르면 없어지게 하기, useState props로 전달하기 , props 사용하여 state를 다른 컴포넌트로 전달하기 (3) | 2023.11.02 |
[React] 버튼 클릭 시 toggle로 CSS style 바꾸는 방법, 버튼 클릭 시 요소 숨기기, 펼치기 (6) | 2023.10.28 |
[React] 프로필 사진 업로더 만들기, 프로필 변경/삭제/추가, 프로필 페이지 만들기 (4) | 2023.10.27 |
[React] useReducer를 코드에 적용하기 (emotion diary 프로젝트 2탄) (1) | 2023.10.25 |