본문 바로가기
Frontend/Project(개인 기록용)

게시글 일부만 로드(클릭시 조건에 따라 추가 로드)

by Johnny_gon 2023. 6. 8.
728x90
반응형

 

게시글이 늘어날 경우를 대비해서 부분적으로 불러올 수 있는 관련 메서드를 찾아봤습니다.
mongoose에서 제공하는 limit() 메서드를 사용하면 조건을 줘서 일부 doc만 불러올 수 있다고 합니다.

 

아래 참고 링크의 내용을 간략하게 보자면 find() 메소드를 사용하면 모든 document 들을 출력해주기 때문에

 limit() 메소드와 skip() 메소드를 통하여 보이는 출력물의 갯수를 제한 할 수 있다고 합니다.

 

 

server 코드

아래처럼 체이닝으로 넣어주고 limit(5)로 설정하여 5개의 doc만 불러올 수 있게 하였습니다.

 
   router.post("/list", (req, res) => {
     let sort = {};
     if (req.body.sort === "최신글") {
       sort.createdAt = -1;
     } else {
       sort.repleNum = -1;
     }
     Post.find({
       //제목이나 내용 둘중 하나에만 걸려도 return으로 $or사용
       $or: [
         ////$regex = cient에서 search 값이 포함 되는 데이터 찾아줍니다.
         { title: { $regex: req.body.search } },
         { content: { $regex: req.body.search } },
       ],
     })
       .populate("author")
       .sort(sort)
       .limit(5) //한번에 찾을 doc의 숫자
       .exec()
       .then((doc) => {
         res.status(200).json({ success: true, postList: doc });
       })
       .catch((err) => {
         res.status(400).json({ success: false });
         console.log(err);
       });
   });
 

 

limit() 관련 참고 https://velopert.com/516

 

[MongoDB] 강좌 4편 find() 메소드 활용 – sort(), limit(), skip() | VELOPERT.LOG

이번 강좌에선 find() 메소드를 더욱 더 활용하기 위해 필요한 sort(), limit(), skip() 메소드에 대해 배워보겠습니다. 그냥 find() 메소드를 사용하면 criteria 에 일치하는 모든 document 들을 출력해주기

velopert.com

 

 

 

클릭시 게시글을 더 불러올 수 있는 버튼을 만들어줍니다.

버튼은 framer의 motion을 사용해서 만들었습니다.

 
 const [loadMore, setLoadMore] = useState(true);
 

 

   
     <FooterDiv>
       <motion.button
         className="square"
         whileHover={{ scaleX: 1.2 }}
       >
         <img src={more} alt="더보기" />
       </motion.button>
     </FooterDiv>
 

 

버튼 참조   https://www.framer.com/motion/

 

 

client 코드 

 

useState로 skip을 0으로 초기 설정하고

setSkip에 postList의 length를 주고

body에 넣어서 server에 보냅니다.

 
   const [skip, setSkip] = useState(0);
 
  
   const getPostLoadMore = () => {
     let body = {
       sort: sort,
       search: search,
       skip: skip,
     };
   
     axios
       .post("/api/post/list", body)
       .then((res) => {
         if (res.data.success) {
           //0 ~ 4번째 들고옴 5개
           setPostList([...res.data.postList]);
           setSkip(res.data.postList.length);
         }
       })
       .catch((err) => {
         console.log(err);
       });
    };
 

 

 

server 코드

 

client에서 body로 보낸 skip(req.body.skip)을 추가해 줍니다.

 
   router.post("/list", (req, res) => {
    let sort = {};
    if (req.body.sort === "최신글") {
      sort.createdAt = -1;
    } else {
      //인기글
      sort.repleNum = -1;
    }
    Post.find({
      $or: [
        { title: { $regex: req.body.search } },
        { content: { $regex: req.body.search } },
      ],
    })
      .populate("author")
      .sort(sort)
      //skip초기값 0이라 0~4까지 게시글을 찾습니다.
      .skip(req.body.skip)
      .limit(5) //한번에 찾을 doc의 숫자
      .exec()
      .then((doc) => {
        res.status(200).json({ success: true, postList: doc });
      })
      .catch((err) => {
        res.status(400).json({ success: false });
        console.log(err);
      });
  });
 

 

 

버튼에 getPostLoadMore 함수를 만들어 줍니다.

   
 <FooterDiv>
   <motion.button
     className="square"
     whileHover={{ scaleX: 1.2 }}
     onClick={getPostLoadMore}
   >
     <img src={more} alt="더보기" />
   </motion.button>
  </FooterDiv>
 

 

 

 

더 불러오기 버튼 클릭시 기존 5개 게시글 뒤로 이어서 불러오는게 아니라

기존 5개글 자리에 대체되어 기존글 사라지는 현상 발생.

 

 

getPostLoadMore 함수에서 코드 수정

기존에 들고 있던 postList도 같이 넣어줘서 기존 글이랑  불러온 글 대체 현상 해결

         
   setPostList([...postList, ...res.data.postList]);
 

 

코드 수정 skip 추가

         
   setSkip(skip + res.data.postList.length);
 

 

 

글 limit 5개로 정했는데 서버에 글이 7개라면 5개 불러오고 나머지 2개를 불러오는 현상 발생시 더 불러오기 버튼 사라지게..

 
   const [loadMore, setLoadMore] = useState(true);
 

 

서버 게시글 length 5개 이하일 때 false로 설정

         
   if (res.data.postList.length < 5) {
      setLoadMore(false);
      }
 

 

true 일 때 버튼 보이고 false 일 때 버튼 사라집니다.

 
   {loadMore && (
     <FooterDiv>
       <motion.button
         className="square"
         whileHover={{ scaleX: 1.2 }}
         onClick={getPostLoadMore}
       >
         <img src={more} alt="더보기" />
       </motion.button>
     </FooterDiv>
   )}
 

 

 

게시글 검색 기능 함수

 
  const listChange = () => {
    setSkip(0);
    let body = {
      sort: sort,
      search: search,
      skip: 0,
    };

    axios
      .post("/api/post/list", body)
      .then((res) => {
        console.log(res);
        if (res.data.success) {
          //0 ~ 4번째 들고옴 5개
          setPostList([...res.data.postList]);
          setSkip(res.data.postList.length);
          if (res.data.postList.length < 5) {
            setLoadMore(false);
          }
          if (res.data.postList.length === 0) {
            setLoadMore(false);
          }
          setLoading(true);
        }
      })
      .catch((err) => {
        console.log(err);
      });
  };
 
728x90
반응형