티스토리 뷰

[React] Redux-saga , react infinite scroll  구현하기 코드예시


안녕하세요. 이번포스팅에서는 리액트에서, 리덕스사가를 활용해 무한스크롤을 구현하는 방법에 대해 포스팅 하려고합니다.

 

예시코드를 통해, 이런식으로 구현할 수 있구나 정도로 원리만 파악하시고, 

직접 구현하실 때는 , 본인의 코드 스타일에 맞게 구현 하시면 될 것 같아요 ! 

 

 

@ 컴포넌트 코드

// index.js

const Home = () => {
  const dispatch = useDispatch();
  const { me } = useSelector((state) => state.user);
  const { mainPosts, hasMorePosts, loadPostsLoading } = useSelector((state) => state.post);
  const imageInput = useRef();

  useEffect(() => {
    dispatch({
      type: LOAD_POSTS_REQUEST,
    });
  }, []);

  // scrollY : 스크롤을 얼마나 내렸는지
  // clientHeight : 화면에 보이는 길이
  // scrollHeight : 총 길이
  // 화면을 끝까지 내렷을 때, scrollY + clientHeight === scrollHeight
  useEffect(() => {
    function onScroll() {
      if (
        window.scrollY + document.documentElement.clientHeight >
        document.documentElement.scrollHeight - 300
      ) {
      // hasMorePosts는 최대 게시물수를 제한하기 위한 변수입니다. 
      // 최대 게시물을 제한하지 않으신다면 빼셔도 괜찮아요.
      // loadPostsLoading 상태값을 확인해, 로딩중일 경우에 요청을 다시 보내지 않도록 막아주었습니다.
        if (hasMorePosts && !loadPostsLoading) {
          dispatch({
            type: LOAD_POSTS_REQUEST,
          });
        }
      }
    }
    window.addEventListener('scroll', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
    };
  }, [hasMorePosts, loadPostsLoading]);

@ reducer 코드

// reducers/post.js

const reducer = (state = initialState, action) =>
  produce(state, (draft) => {
    switch (action.type) {
      case LOAD_POSTS_REQUEST:
        draft.loadPostsLoading = true;
        draft.loadPostsDone = false;
        draft.loadPostsError = null;
        break;
      case LOAD_POSTS_SUCCESS:
        draft.loadPostsLoading = false;
        draft.loadPostsDone = true;
        draft.mainPosts = action.data.concat(draft.mainPosts);
        draft.hasMorePosts = draft.mainPosts.length < 50;
        break;
      case LOAD_POSTS_FAILURE:
        draft.loadPostsLoading = false;
        draft.loadPostsError = action.error;
        break;
     default:
        break;
    }
  });

@ saga 코드

// sagas/post.js

// delay를 사용해 비동기 처리를 해주었습니다.
// 실제프로젝트에서 백엔드서버가 있을 경우에는 delay 부분 빼주시고 
// 서버에 비동기요청하는 코드로 넣어주시면 될 것 같아요.
// generateDummyPost(n) 은 임의로 만들어 놓은 더미포스트를 n개식 가져오는 함수입니다.

function* loadPosts(action) {
  try {
    yield delay(1000);
    const id = shortId.generate();
    yield put({
      type: LOAD_POSTS_SUCCESS,
      data: generateDummyPost(10),
    });
  } catch (err) {
    yield put({
      type: LOAD_POSTS_FAILURE,
      data: err.response.data,
    });
  }
}

// throttle 을 사용해 3초 이내의 요청에 대한 추가적인 응답을 받지 않도록 처리해 주었습니다.
// 단, 백엔드단으로 요청은 계속 날라가니 이부분에 대한 처리도 필요합니다 !!  index.js부분 참고@
function* watchLoadPosts() {
  yield throttle(3000, LOAD_POSTS_REQUEST, loadPosts);
}

export default function* postSaga() {
  yield all([
    fork(watchLoadPosts),
  ]);
}
댓글
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함