9.5.7 커스텀 Hook을 작성해 컴포넌트 리팩토링하기

    posts.js 파일에서 Firestore에 포스트를 조회하는 함수를 작성할 때 함수가 비슷해지자 getPosts를 재사용할 수 있는 형태로 리팩토링해줬습니다. 만약 컴포넌트에서 비슷한 UI가 반복된다면 컴포넌트를 분리해 재사용하면 되는데요. 이때 컴포넌트의 로직만 반복된다면 어떻게 할까요? 그럴 때는 커스텀(Custom) Hook을 만들어서 로직을 재사용할 수 있습니다.

    프로젝트의 루트 디렉터리에 hooks 디렉터리를 만들고 그 안에 usePosts라는 함수를 다음과 같이 작성해보세요. 기존에 만든 Profile 컴포넌트에서 필요한 코드를 가져와 붙여넣으면 됩니다.

    hooks/usePosts.js

    import {useEffect, useState} from 'react';
    import {getNewerPosts, getOlderPosts, getPosts, PAGE_SIZE} from '../lib/posts';
    
    export default function usePosts(userId) {
      const [posts, setPosts] = useState(null);
      const [noMorePost, setNoMorePost] = useState(false);
      const [refreshing, setRefreshing] = useState(false);
    
      const onLoadMore = async () => {
        if (noMorePost || !posts || posts.length < PAGE_SIZE) {
          return;
        }
        const lastPost = posts[posts.length - 1];
        const olderPosts = await getOlderPosts(lastPost.id, userId);
        if (olderPosts.length < PAGE_SIZE) {
          setNoMorePost(true);
        }
        setPosts(posts.concat(olderPosts));
      };
    
      const onRefresh = async () => {
        if (!posts || posts.length === 0 || refreshing) {
          return;
        }
        const firstPost = posts[0];
        setRefreshing(true);
        const newerPosts = await getNewerPosts(firstPost.id, userId);
        setRefreshing(false);
        if (newerPosts.length === 0) {
          return;
        }
        setPosts(newerPosts.concat(posts));
      };
    
      useEffect(() => {
        getPosts({userId}).then((_posts) => {
          setPosts(_posts);
          if (_posts.length < PAGE_SIZE) {
            setNoMorePost(true);
          }
        });
      }, [userId]);
    
      return {
        posts,
        noMorePost,
        refreshing,
        onLoadMore,
        onRefresh,
      };
    }
    신간 소식 구독하기
    뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.