{ //리스트 const [list, setList] = useState([]); const [slicedList, setSlicedList] = useState([]); //수치값 const itemHeight = 45; const nodePadding = 20; const scrollViewPortHeight = 490; const [totalContainerHeight, setTotalContainerHeight] = useState(0); const { scrollTop, scrollContainerRef } = useScroll( itemHeight, list, filteredList ); //visible 노드 자르기 위한 수치 const startIndex = Math.max( Math.floor(scrollTop / itemHeight) - nodePadding, 0 ); const visibleNodeCount = Math.floor( scrollViewPortHeight / itemHeight + 2 * nodePadding ); const endIndex = startIndex + visibleNodeCount; c"> { //리스트 const [list, setList] = useState([]); const [slicedList, setSlicedList] = useState([]); //수치값 const itemHeight = 45; const nodePadding = 20; const scrollViewPortHeight = 490; const [totalContainerHeight, setTotalContainerHeight] = useState(0); const { scrollTop, scrollContainerRef } = useScroll( itemHeight, list, filteredList ); //visible 노드 자르기 위한 수치 const startIndex = Math.max( Math.floor(scrollTop / itemHeight) - nodePadding, 0 ); const visibleNodeCount = Math.floor( scrollViewPortHeight / itemHeight + 2 * nodePadding ); const endIndex = startIndex + visibleNodeCount; c"> { //리스트 const [list, setList] = useState([]); const [slicedList, setSlicedList] = useState([]); //수치값 const itemHeight = 45; const nodePadding = 20; const scrollViewPortHeight = 490; const [totalContainerHeight, setTotalContainerHeight] = useState(0); const { scrollTop, scrollContainerRef } = useScroll( itemHeight, list, filteredList ); //visible 노드 자르기 위한 수치 const startIndex = Math.max( Math.floor(scrollTop / itemHeight) - nodePadding, 0 ); const visibleNodeCount = Math.floor( scrollViewPortHeight / itemHeight + 2 * nodePadding ); const endIndex = startIndex + visibleNodeCount; c">
import styled from "styled-components";
import ResultItem from "./ResultItem";
import fetchData from "../../../api/fetchData";
import useScroll from "../../../hooks/useScroll";
import { useEffect, useState, useCallback } from "react";
import { PayDataListProps } from "./model";

const ResultList = () => {
  //리스트
  const [list, setList] = useState<PayDataListProps[]>([]);
  const [slicedList, setSlicedList] = useState<PayDataListProps[]>([]);

  //수치값
  const itemHeight = 45;
  const nodePadding = 20;
  const scrollViewPortHeight = 490;
  const [totalContainerHeight, setTotalContainerHeight] = useState<number>(0);
  const { scrollTop, scrollContainerRef } = useScroll(
    itemHeight,
    list,
    filteredList
  );

  //visible 노드 자르기 위한 수치
  const startIndex = Math.max(
    Math.floor(scrollTop / itemHeight) - nodePadding,
    0
  );
  const visibleNodeCount = Math.floor(
    scrollViewPortHeight / itemHeight + 2 * nodePadding
  );
  const endIndex = startIndex + visibleNodeCount;
  const offsetY = startIndex * itemHeight;

  //전체 데이터 가져오기
  const getMoreData = useCallback(async () => {
    try {
      const payData = await fetchData();
      setList(payData);
      setTotalContainerHeight(payData.length * itemHeight);
    } catch (e) {
      console.error(e);
    }
  }, []);

  useEffect(() => {
    getMoreData();
  }, []);

  //visible nodes 자르기
  useEffect(() => {
    setSlicedList(list.slice(startIndex, endIndex));
  }, [list, startIndex]);

  return (
    <ResultListBox ref={scrollContainerRef} height={scrollViewPortHeight}>
      <TotalItemBox height={totalContainerHeight}>
        <VisibleContentsBox offsetY={offsetY}>
          {slicedList.length === 0 ? (
            <NoResult>
              <div>결과가 없어요</div>
              <div>검색조건을 확인해주세요</div>
            </NoResult>
          ) : (
            slicedList.map((item) => (
              <ResultItem key={item.payID} itemHeight={itemHeight} {...item} />
            ))
          )}
        </VisibleContentsBox>
      </TotalItemBox>
    </ResultListBox>
  );
};

export default ResultList;

//styled-components
const ResultListBox = styled.div<{ height: number }>`
  height: ${(props) => `${props.height}px`};
  overflow-y: auto;
  padding-right: 1.2rem;
`;

const TotalItemBox = styled.div<{ height: number }>`
  height: ${(props) => `${props.height}px`};
  position: relative;
`;

const VisibleContentsBox = styled.div<{ offsetY: number }>`
  position: absolute;
  width: 100%;
  transform: translateY(
    ${(props) => props.offsetY}px
  ); //px 단위를 안넣어주면 인식이 잘 안됨
`;

const NoResult = styled.div`
  text-align: center;
  padding: 8rem 0;
  font-size: 1.8rem;
  font-weight: bold;

  > div {
    padding: 0.8rem;
  }
`;