더북(TheBook)

startAfter와 비슷한 함수로는 startAt이 있습니다. 두 함수의 차이점은 파라미터로 넣은 정보를 포함하느냐의 여부입니다. startAfter는 파라미터로 받은 정보를 제외한 데이터를 반환하고, startAt은 파라미터로 받은 정보를 포함해 데이터를 반환합니다.

함수를 다 작성했으면 이 함수를 FeedScreen에서 사용해봅시다. FlatList에서 스크롤을 맨 아래까지 내렸을 때 이 함수를 호출하고 결과물을 posts 상태에 추가해주면 됩니다.

screens/FeedScreen.js

import React, {useEffect, useState} from 'react';
import {ActivityIndicator, FlatList, StyleSheet} from 'react-native';
import PostCard from '../components/PostCard';
import {getOlderPosts, getPosts, PAGE_SIZE} from '../lib/posts';

function FeedScreen() {
  const [posts, setPosts] = useState(null);
  // 마지막 포스트까지 조회했음을 명시하는 상태
  const [noMorePost, setNoMorePost] = useState(false);
  useEffect(() => {
    // 컴포넌트가 처음 마운트될 때 포스트 목록을 조회한 후 posts 상태에 담기
    getPosts().then(setPosts);
  }, []);

  const onLoadMore = async () => {
    if (noMorePost || !posts || posts.length < PAGE_SIZE) {
      return;
    }
    const lastPost = posts[posts.length - 1];
    const olderPosts = await getOlderPosts(lastPost.id);
    if (olderPosts.length < PAGE_SIZE) {
      setNoMorePost(true);
    }
    setPosts(posts.concat(olderPosts));
  };

  return (
    <FlatList
      data={posts}
      renderItem={renderItem}
      keyExtractor={(item) => item.id}
      contentContainerStyle={styles.container}
      onEndReached={onLoadMore}
      onEndReachedThreshold={0.75}
      ListFooterComponent={
        !noMorePost && (
          <ActivityIndicator style={styles.spinner} size={32} color="#6200ee" />
        )
      }
    />
  );
}

const renderItem = ({item}) => (...);

const styles = StyleSheet.create({
  container: {
    paddingBottom: 48,
  },
  spinner: {
    height: 64,
  },
});

export default FeedScreen;

posts 상태를 업데이트하는 것 외에도, 더 이상 불러올 포스트가 없다는 것을 의미하는 noMorePost라는 상태를 만들어서 마지막으로 불러온 포스트의 개수가 PAGE_SIZE 미만이라면 다음 포스트를 더 이상 불러오지 않도록 구현해줬습니다. 그리고 noMorePost 값에 따라 스크롤을 맨 아래까지 내렸을 때 ActivityIndicator가 나타나도록 했습니다. 만약 추가로 불러올 수 있는 포스트가 있으면 스피너가 보이고 그렇지 않으면 보이지 않는 것이죠.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.