본문 바로가기

Libraries/React

[React] 게시글 더보기, 접기 토글 버튼 만들기

728x90

 

 

게시글 더보기, 접기 토글 버튼을 만드는 법에 대해서 알아보자!

 

 

 

 만들 예제의 완성본 

 

글자수가 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>

 

 

 

 

 

 

앞서 설명한 기능은 이런식으로 게시글을 만들 때 사용하면 유용하다.

 

 

728x90