React Native: Flatlist infinite scroll - seltsames Verhalten

zlep

Banned
Registriert
Feb. 2016
Beiträge
126
Hallo,

ich versuche zur Zeit ein infinite scroll in mein React Native Projekt zu implementieren.

Anbei mein Code:

API aufrufen (mit useEffect Hook)
Code:
  useEffect(() => {
    const loadProducts = async () => {
      let response = await fetch(
        `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
      );
      let results = await response.json();
      //console.log(results);
      if (results) {
        setProducts([...products, ...results]);
      }
    };
    loadProducts();
  }, [page]);

Meine Flatlist
Code:
    <FlatList
      data={products}
      keyExtractor={(item, index) => item.id}
      renderItem={renderGridItem}
      onEndReached={loadMore}
      onEndReachedThreshold={0}
    />

LoadMore Function
Code:
  loadMore = () => {
    setPage(page + 1);
    console.log(page);
  };

Und die useState
Code:
  const [products, setProducts] = useState([]);
  const [page, setPage] = useState(1);

Prinzipiell funktioniert es auch. Das Problem ist nur, dass sich die page Variable komisch verhält. Im console log sehe ich, dass sie manchmal direkt 2 mal aufgerufen wird. Also sie geht von 1 direkt auf 2 und 3. Manchmal wird aber auch direkt beim ersten Zugriff 1 und 2 geladen.

Jemand eine Idee woran das liegen könnte?
Vielen Dank
 
Was passiert, wenn du aus setPage(page + 1); das hier machst: setPage(page => page + 1); ?
 
mastaqz schrieb:
Was passiert, wenn du aus setPage(page + 1); das hier machst: setPage(page => page + 1); ?
Leider kein Unterschied. Es werden immer noch direkt page 2 und page 3 geladen.
 
Meine Vermutung wäre, dass es mit dem "onEndReached" zusammenhängt. Wenn die Liste initial komplett leer ist, wird vermutlich sofort onEndReached aufgerufen und dadurch weitere Daten gefetched.

Falls das wirklich das Problem ist, wäre es eventuell lösbar, indem man eine "isFetching"-Variable einführt, damit eben immer nur maximal ein Fetch läuft:

Code:
let isFetching = useRef(false); // NEU
useEffect(() => {
    const loadProducts = async () => {
        isFetching.current = true; // NEU
        let response = await fetch(
            `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=10`
        );
        let results = await response.json();
        isFetching.current = false; // NEU
        if (results) {
            setProducts([...products, ...results]);
        }
    };
    loadProducts();
}, [page]);
const loadMore = () => {
    if(isFetching.current) return; // NEU
    setPage(page + 1);
    console.log(page);
};
 
@cx01 Leider keine Änderung. Wirklich ein sehr seltsames Problem.
Es gibt im Internet leider auch kein wirkliches Beispiel mit useEffect hook und infinite scroll einer Flatlist.

Das komische ist, dass wenn ich in
ListFooterComponent einen loadMore Button einbaue, funktioniert es einwandfrei. Im Prinzip ist das ja das gleiche nur halt nicht automatisch.
 
Ich hab dein Beispiel mal lokal getestet. Hier lädt er auch mehrere Seiten direkt hintereinander; aber nur dann, wenn die Gesamthöhe aller bisherigen Items nicht ausreicht, den Bildschirm zu füllen. Wenn ich aber den Items explizit z. B. eine "height:200" gebe, dann lädt er erstmal nur eine Seite.
 
@cx01 Interessant, danke. Aber eine Lösung ist das ja leider auch nicht. Ist das dann ein Bug in react flatlist?
 
Meiner Ansicht nach funktioniert es genau so, wie es sollte. Wenn der Inhalt nicht ausreicht, um den Bildschirm zu füllen, ist es doch korrekt, dass er "onEndReached" aufruft, da ja tatsächlich das Ende erreicht ist.
 
Zurück
Oben