ReactJS - 커스텀 Hooks: 무한 스크롤 마스터링

안녕하세요, React 개발자 지망생 여러분! 오늘 우리는 커스텀 Hooks의 세계로 흥미로운 여정을 떠납니다. 특히 무한 스크롤 기능을 구현하는 것에 중점을 두겠습니다. 여러분의 친구 겸 컴퓨터 과학 교사로서, 저는 이 과정을 단계별로 안내해 드리겠습니다. 모든 개념을 제대로 이해하실 수 있도록 하겠습니다. 그러니 좋아하는 음료를 마시며 편안하게 앉아, 함께 들어보겠습니다!

ReactJS - Custom Hooks

커스텀 Hooks 이해하기

무한 스크롤에 들어가기 전에, 커스텀 Hooks에 대해 잠시 이야기해 보겠습니다. React에서 Hooks는 함수 컴포넌트에서 React 상태와 라이프사이클 기능을 "hook into"할 수 있게 해주는 함수입니다. 커스텀 Hooks는 다른 Hooks를 사용하고 컴포넌트 간에 공유할 수 있는 함수입니다.

커스텀 Hooks를 개인적인 스위스 아ーノ이 knife로 생각해 보세요. 그들은 컴포넌트 로직을 재사용 가능한 함수로 추출하여 코드를 깨끗하고 모듈러하게 만들어 줍니다.

무한 스크롤 기능 구현하기

이제 우리의 별이 되는 무한 스크롤 기능을 다루어 보겠습니다. 소셜 미디어 플랫폼이나 뉴스 웹사이트에서 자주 겪는 기능인 무한 스크롤은 사용자 경험을 향상시키는 좋은 방법입니다. 페이지네이션 없이 자연스럽게 더 많은 콘텐츠를 보여줍니다.

무한 스크롤의 기본

무한 스크롤의 핵심은 세 가지 주요 단계로 구성됩니다:

  1. 사용자가 페이지의 하단에 스크롤한 것을 감지하기
  2. 더 많은 데이터를 로드하는 요청을 트리거하기
  3. 새로운 데이터를 기존 콘텐츠에 추가하기

이를 단계별로 나누어 커스텀 Hook을 만들어 보겠습니다.

useInfiniteScroll Hook 구현하기

우리는 useInfiniteScroll이라는 커스텀 Hook을 만들겠습니다. 이 Hook은 언제 콘텐츠를 로드해야 하는지 감지하고, 필요한 상태와 함수를 제공하여 무한 스크롤을 컴포넌트에 구현할 수 있게 합니다.

Hook의 기본 구조는 다음과 같습니다:

import { useState, useEffect } from 'react';

const useInfiniteScroll = (callback) => {
const [isFetching, setIsFetching] = useState(false);

useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);

useEffect(() => {
if (!isFetching) return;
callback();
}, [isFetching]);

function handleScroll() {
if (window.innerHeight + document.documentElement.scrollTop !== document.documentElement.offsetHeight || isFetching) return;
setIsFetching(true);
}

return [isFetching, setIsFetching];
};

export default useInfiniteScroll;

이를 조각별로 설명하겠습니다:

  1. useStateuseEffect를 React에서 import합니다. 이는 우리의 커스텀 Hook의 기본 블록입니다.

  2. useInfiniteScroll Hook은 callback 함수를 인자로 받습니다. 이 함수는 트리거될 때 데이터를 로드하는 함수입니다.

  3. useState를 사용하여 isFetching 상태를 생성합니다. 이는 현재 데이터를 로드하고 있는지 추적합니다.

  4. 첫 번째 useEffect는 컴포넌트가 마운트될 때 스크롤 이벤트 리스너를 추가하고, 언마운트될 때 리스너를 제거합니다. 이는 메모리 누수를 방지합니다.

  5. 두 번째 useEffectisFetching의 변경을 감시합니다. isFetching이 참이 되면 callback 함수를 호출합니다.

  6. handleScroll 함수는 마법이 일어나는 곳입니다. 사용자가 페이지 하단에 스크롤하고 현재 데이터를 로드하고 있지 않다면 isFetching을 참으로 설정합니다.

  7. 마지막으로 isFetchingsetIsFetching을 반환하여 컴포넌트에서 이 상태와 업데이트 함수에 접근할 수 있게 합니다.

이제 이 Hook을 컴포넌트에서 사용해 보겠습니다:

import React, { useState } from 'react';
import useInfiniteScroll from './useInfiniteScroll';

const InfiniteScrollComponent = () => {
const [items, setItems] = useState([]);
const [isFetching, setIsFetching] = useInfiniteScroll(fetchMoreListItems);

function fetchMoreListItems() {
// API 호출 시뮬레이션
setTimeout(() => {
setItems(prevItems => ([...prevItems, ...Array(20).fill(0).map((_, i) => ({ id: prevItems.length + i, name: `Item ${prevItems.length + i + 1}` }))]));
setIsFetching(false);
}, 2000);
}

return (
<div>
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
{isFetching && 'Fetching more list items...'}
</div>
);
};

export default InfiniteScrollComponent;

이 컴포넌트에서:

  1. 우리는 useInfiniteScroll Hook을 사용하여 fetchMoreListItems 함수를 전달합니다.
  2. fetchMoreListItems는 API 호출을 시뮬레이션하여 2초 후에 20개의 새로운 아이템을 추가합니다.
  3. 목록 아이템을 렌더링하고 isFetching이 참이면 로딩 메시지를 표시합니다.

이제 우리는 커스텀 React Hook을 사용하여 완전한 무한 스크롤 구현을 완료했습니다!

기억해 두세요, 커스텀 Hooks의 아름다움은 그들의 재사용성에 있습니다. 이제 useInfiniteScroll Hook을 사용하여 어디서든 무한 스크롤 기능을 쉽게 통합할 수 있습니다.

결론

커스텀 Hooks는 React에서 강력한 기능으로, 재사용 가능한 로직을 만들 수 있게 해줍니다. 무한 스크롤을 커스텀 Hook으로 구현함으로써, 우리는 유연하고 재사용 가능한 솔루션을 만들었습니다.

React 여정을 계속하면서, 계속 커스텀 Hooks를 탐구하고 만들어 보세요. 그들은 코드를 반복 없이 유지하고 깨끗하며 모듈러하게 만드는 훌륭한 방법입니다.

행복하게 코딩하시고, 무한한 스크롤이 되세요! ??

방법 설명
useInfiniteScroll(callback) 무한 스크롤을 구현하기 위한 커스텀 Hook
useState(initialState) 함수 컴포넌트에 상태 추가를 위한 React Hook
useEffect(effect, dependencies) 함수 컴포넌트에서 사이드 이펙트를 수행하기 위한 React Hook
addEventListener(event, handler) 이벤트 핸들러를 엘리먼트에 추가하기 위한 Web API
removeEventListener(event, handler) 이벤트 핸들러를 엘리먼트에서 제거하기 위한 Web API
setTimeout(callback, delay) 지정된 지연 시간 후에 함수를 실행하기 위한 Web API

Credits: Image by storyset