skip to Main Content

Airtable only gives 100 records by default on API calls to load more than 100 records I have used offset address but when all the records are called I want to show them in batches when a user scrolls to the end more records should get loaded.

What I have tried …

const apiKey = "API_KEY";
const baseId = "BaseId";
const tableName = "Table1";
const viewName = "Grid view";
const pageSize = 10;
const base = new Airtable({ apiKey }).base(baseId);

const Home = () => {
  const [records, setRecords] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [offset, setOffset] = useState(0);

  useEffect(() => {
    setIsLoading(true);
    loadRecords();
  }, []);

  async function loadRecords() {
    setIsLoading(true);

    const response = await base(tableName)
      .select({ view: viewName, pageSize, offset })
      .all();

    const newRecords = [...records, ...response];
    setRecords(newRecords);

    if (response.offset) {
      setOffset(response.offset);
    } else {
      setOffset(0);
    }

    setIsLoading(false);
    console.log("Loaded records:", response);
  }
  function renderRecord({ item }) {
    return <CardView img={item.fields.wallpaper} />;
  }

  function renderFooter() {
    return isLoading ? (
      <View style={styles.loader}>
        <ActivityIndicator size="large" />
      </View>
    ) : null;
  }

  function handleLoadMore() {
    if (!isLoading && offset !== undefined) {
      loadRecords();
    }
  }

  return (
    <View style={styles.container}>
      <FlatList
        data={records}
        renderItem={renderRecord}
        numColumns={numColumns}
        keyExtractor={(item) => item.id}
        ListFooterComponent={renderFooter}
        onEndReached={handleLoadMore}
        onEndReachedThreshold={0}
        initialNumToRender={pageSize}
      />
    </View>
  );
};

export default Home;

With this code all records are loading at once not in batches can somebody help me where am I going wrong

2

Answers


  1. you can use the following props to help you archive what you want

    to let flatlist render some amount of component every tile while the user is scrolling you can use maxToRenderPerBatch

    It is a VirtualizedList prop that can be passed through FlatList. This >controls the amount of items rendered per batch, which is the next chunk of items rendered on every scroll.
    Pros: Setting a bigger number means less visual blank areas when scrolling (increases the fill rate).
    Cons: More items per batch means longer periods of JavaScript execution potentially blocking other event processing, like presses, hurting responsiveness.

    <FlatList
                data={records}
                renderItem={renderRecord}
                numColumns={numColumns}
                getItemLayout={getItemLayout}
                initialNumToRender={2}
                maxToRenderPerBatch={2}
                windowSize={5}
                ListFooterComponent={renderFooter}
                initialNumToRender={2} <=== important lines
                maxToRenderPerBatch={2} <=== important lines
                ...
              />
    

    you can read this article to help you Optimizing your flatlist : https://reactnative.dev/docs/optimizing-flatlist-configuration

    Login or Signup to reply.
  2. import React, { useEffect, useState } from 'react';
    import { View, FlatList, ActivityIndicator } from 'react-native';
    import Airtable from 'airtable';
    import CardView from './CardView';
    import styles from './styles';
    
    const apiKey = "API_KEY";
    const baseId = "BaseId";
    const tableName = "Table1";
    const viewName = "Grid view";
    const base = new Airtable({ apiKey }).base(baseId);
    
    const Home = () => {
      const [records, setRecords] = useState([]);
      const [isLoading, setIsLoading] = useState(false);
      const [isFetchingMore, setIsFetchingMore] = useState(false);
      const [offset, setOffset] = useState(0);
      const numColumns = 2; // Specify the number of columns for the FlatList
    
      useEffect(() => {
        setIsLoading(true);
        loadRecords();
      }, []);
    
      async function loadRecords() {
        setIsLoading(true);
        setIsFetchingMore(true);
    
        try {
          const response = await base(tableName)
            .select({ view: viewName, pageSize: records.length + 10, offset })
            .all();
    
          setRecords(response);
          setIsLoading(false);
          setIsFetchingMore(false);
          console.log("Loaded records:", response);
        } catch (error) {
          console.error("Error loading records:", error);
          setIsLoading(false);
          setIsFetchingMore(false);
        }
      }
    
      function renderRecord({ item }) {
        return <CardView img={item.fields.wallpaper} />;
      }
    
      function renderFooter() {
        return isFetchingMore ? (
          <View style={styles.loader}>
            <ActivityIndicator size="large" />
          </View>
        ) : null;
      }
    
      function handleLoadMore() {
        if (!isFetchingMore) {
          setOffset(records.length);
          loadRecords();
        }
      }
    
      return (
        <View style={styles.container}>
          <FlatList
            data={records}
            renderItem={renderRecord}
            numColumns={numColumns}
            keyExtractor={(item) => item.id}
            ListFooterComponent={renderFooter}
            onEndReached={handleLoadMore}
            onEndReachedThreshold={0.5} // Adjust the threshold as per your requirement
            initialNumToRender={10} // Specify the initial number of records to render
          />
        </View>
      );
    };
    
    export default Home;
    

    the pageSize is dynamically set as records.length + 10 on each load to fetch more records. The offset is not used in this case. Instead, the records.length serves as the starting index for fetching new records. The isFetchingMore state is used to prevent multiple simultaneous fetch requests.

    When the user scrolls to the end of the list, the handleLoadMore function is called, which triggers the loadRecords function to fetch more records based on the increased pageSize. The renderFooter function displays an activity indicator when new records are being fetched.

    Hope this will help!!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search