지난 skeleton의 오류와 수정

미마모코딩·2022년 11월 22일
0

팀 프로젝트 경험

목록 보기
5/6
post-thumbnail

지난번 react suspense에 대한 포스팅을 올렸을때 원하는대로 동작을 하지않았다.

스켈레톤 컴포넌트와 연결돼서 랜더링 되는게 아니라 뚝 뚝 끊겨서 랜더링이 되어서 크게 당황을 했는데 오늘 생각한 방법은 state를 다시 만들어서 결국 해야하나?라는 고민이 커졌다.

제일 큰 문제점은 내가 이전에 skeleton에 board_item으로 map을돌려 기존의 element들을 화면에 랜더시킨 로직이 문제였다.

데이터를 받아오기 전에 보여줄 컴포넌트가 skeleton인데 ,데이터를 받아 데이터의 랭스만큼 생성한다는게 지금 생각해보면 참 당황스러운 실수였다.

그래서 아래와 같이 개선해서 원하는 동작을 만들어냈다.

<script>
const [boardItems, setBoardItems] = useState<BoardItem[]>([])
  console.log(boardItems.length === 0) // false 였다가 트루로 재랜더링
  const [value, setValue] = useState("")
  const boardItemLenthChecker = boardItems.length == 0
  console.log(boardItemLenthChecker)

  const boardDataRef = useRef<{
    items: BoardItem[]
    isLast: boolean
    nextQuery: Query<DocumentData> | undefined
    board_name: string
  }>({
    items: [],
    isLast: false,
    nextQuery: undefined,
    board_name: board_name_gallery
  })

  const loadMoreItems = () => {
    const { isLast, nextQuery } = boardDataRef.current

    if (!isLast) {
      getboard({ nextQuery: nextQuery ? nextQuery : undefined, board_name: board_name_gallery }).then((res) => {
        const { isLast, nextQueryRef, items } = res
        boardDataRef.current.nextQuery = nextQueryRef
        boardDataRef.current.isLast = isLast
        boardDataRef.current.items = [...boardDataRef.current.items, ...items]
        setBoardItems((prev: BoardItem[]) => [...prev, ...items])
      })
    }
  }

  useEffect(() => {
    loadMoreItems()
  }, [])
  </script>

위 코드들은 데이터를 useEffect로 불러오고 다음쿼리에서 20개씩 더 불러오는 데이터 패칭코드이다.

boardItemLenthChecker은 true 또는 false인 bool값을 반환한다.

위 코드를 토대로

 <InfiniteScroll
              className="scroll_ui"
              next={loadMoreItems}
              hasMore={true}
              loader={<span style={{ display: "none" }}>불러오는 중</span>}
              dataLength={boardItems.length}
            >
              <SkeletonCompo boardItemLenthChecker={boardItemLenthChecker} boardItems={boardItems} value={value} />
            </InfiniteScroll>

위와같이 불값을 반환하는 상수 , 보드아이템, value를 넘겨주었다.

SkeletonCompo로 가보면?

<script>
import SearchList from "@globalComponents/search/SearchList"
import { BoardItem } from "@models/board"
import React, { FC } from "react"

import "react-loading-skeleton/dist/skeleton.css"
import * as S from "./SkeletonCompo.style"
interface Props {
  boardItems: BoardItem[]
  value: string
  boardItemLenthChecker: boolean
}
const SkeletonCompo: FC<Props> = ({ boardItems, value, boardItemLenthChecker }) => {
  return (
    <S.Wrapper>
      <ul>
        {boardItemLenthChecker === true ? (
          new Array(10).fill(1).map((_, i) => {
            return (
              <li key={i}>
                <span className="skeleton_title_area"></span>
                <span className="skeleton_contents"></span>
              </li>
            )
          })
        ) : (
          <SearchList boardItems={boardItems} value={value}></SearchList>
        )}
      </ul>
    </S.Wrapper>
  )
}

export default SkeletonCompo
</script>

boardItemLenthChecker === true은 뭘 의미할까?

데이터를 패칭해서 set해주기전이라면 lenth가 0일것이다.

데이터가 들어왔다면? 1이상일것이다.

위의 조건으로 조건부랜더를 통해

가짜배열을 하나 만들어주고 값은 1로 채워주었다. 또한 그걸 토대로 map을 돌려 스켈레톤컴포넌트의 아이템들을 리턴한다.

데이터가 들어왔다면? 내가 원래 보여주려던 컨텐츠를 리턴한다.

이렇게 state를 만들지 않고 구현에 완료했다.

0개의 댓글