프론트엔드/REACT

[리액트]무한 스크롤 intersection-observer (EASY 버전)

인천쓰 2023. 11. 16. 15:48
반응형

리액트로 미니 프로젝트중

무한 스크롤 /페이지네이션 중에 구현하기위해 고민을하던 찰라 , 

추후 하이브리드 웹 (앱도가능) 을 위해 무한스크롤을 구현하기로 결정하였다.

 

일단 이번프로젝트에선 

ORACLE / JDBC / AXIOS / REACT 를 사용하여 구현하였습니다.

 

처음 내 생각으로는 백엔드(JDBC)에서 5개씩 순차적으로 데이터를 리액트로 날려주어 스크롤 마다 이벤트를주어 

출력하면 그대로 나온다고 생각하고 작업 진행하였습니다 .

 

    public List<GoodsVO> GoodsList(String world,String area,Integer count) {
        List<GoodsVO> list = new ArrayList<>();
        String sql = null;
        System.out.println("world : " + world);

        int count1 =(count*5)+1;
        int count2 =(count*5)+5;
        try {
            conn = Common.getConnection();
            stmt = conn.createStatement();
            if(area.equals("ALL")){
                if (world.equals("korea"))
                    sql = "SELECT * FROM (SELECT ROWNUM AS NUM, GOODS_TABLE.* FROM GOODS_TABLE WHERE  I_WORLD='국내')WHERE NUM BETWEEN "+count1+" AND "+count2;
                else sql = "SELECT * FROM (SELECT ROWNUM AS NUM, GOODS_TABLE.* FROM GOODS_TABLE WHERE  I_WORLD='해외')WHERE NUM BETWEEN "+count1+" AND "+count2;
            }else{
                if (world.equals("korea"))
                    sql = "SELECT * FROM (SELECT ROWNUM AS NUM, GOODS_TABLE.* FROM GOODS_TABLE WHERE  I_WORLD='국내' AND I_AREA = '"+area+"')WHERE NUM BETWEEN "+count1+" AND "+count2;
                else sql = "SELECT * FROM (SELECT ROWNUM AS NUM, GOODS_TABLE.* FROM GOODS_TABLE WHERE  I_WORLD='해외' AND I_AREA = '"+area+"')WHERE NUM BETWEEN "+count1+" AND "+count2;
            }

 

 

자바 DAO의 메소드 부문에 값을 count로 받아와 

   int count1 =(count*5)+1;  여기부터
   int count2 =(count*5)+5;  여기까지 출력해주세요 라는 구문을 sql문으로 날려주어 데이터를 받아왔습니다 .

이로서 JDBC 적용 준비끝!

 

 

yarn add react-intersection-observer 라이브러리를 설치

import { useInView } from "react-intersection-observer";
  const [refs,setRefs]=useState(true);

useInView를 사용하여 스크롤 위치값(ref)을 true,false 값으로 변경해 줄꺼임 

  useEffect(() => {
    const GoodsList = async () => {
      try {
        console.log(aeraSelect);
        const resp = await AxiosApi.goodsList(worlds, aeraSelect,count); //전체 조회
        if (resp.status === 200){
          if(resp.data.length > 0){
          console.log(resp.data.length);
          console.log(count);
          console.log(resp.data);
          const list =goodsList.concat(resp.data);
          setGoodsList(list);
          setCount(count+1);
      }}} catch (e) {
        console.log(e);
        setModalOpen(true);
      }
    };
 
      GoodsList();
 
  }, [inView]);

 

 

useEffect를 사용하여 inView값이 변경할떄마다 axios 선언하여 데이터값 출력합니다.

출력시 concat 사용하여 기존 리스트에 데이터값추가하여 setGoodsList에 값을 저장 

또한 다음 값을 불러오기위해 count+1을 추가시켜줍니다.

고로 5> 10 > 15개씩 데이터가 뒤로 붙어가면서 증가하게 됩니다 .

 

  return (
    <>
      {goodsList &&
        goodsList.map((data, index) => (
                   data 갯수만크 리스트 출력
        ))}
        <refstyle what={refs} ref={ ref }> </refstyle>
 
    </>
  );

 

goodsLIst 에 값이 있으면 Map을 사용하여 들어있는갯수만큼 출력 ,

마지막에 ref  값을 넣어 ref가 보일때마다 false가 true 값으로 변경되어 useEffect로 담은 함수를 사용하게 됩니다. 

 

일단 단일 리스트 출력 페이지는 이렇게 구현하면 쉬운 무한스크롤이 가능하게됩니다 .

 

단점 

 

많은 자료 사용시,  데이터가 쌓이는 구조이기떄문에 비효율적임

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

복합 리스트 출력시,

  useEffect(()=>{
    setCount(0);
    setGoodsList([]);
  },[worlds, aeraSelect]);

 

복합 리스트 출력시 쌓이는 리스트값들을 비워주기위해 useEffect 복합사용하여 Count 값과 리스트 값을 초기화 시켜줌,

 

useEffect 두개 동시에사용시 값이 부딪히는 에러 발생하여 출력 useEffect 아래

 

    const timer =setTimeout(()=>{
    },2000)

    return ()=>{
      clearTimeout(timer);
      GoodsList();
    }

 

타이머를 걸어 useEffect후 랜더링 실시하여 사용하였습니다. 

 

결과 

 

반응형