Files
iNaturalistReactNative/src/sharedHooks/useInfiniteObservationsScroll.js
Johannes Klein 3d9f2c3040 Refactor lodash function imports (#3348)
* Change destructured imports to individual imports

* Change full lodash imports to individual function imports

* Remove unused imports

* One more
2026-02-03 18:12:48 +01:00

117 lines
3.0 KiB
JavaScript

// @flow
import { searchObservations } from "api/observations";
import flatten from "lodash/flatten";
import last from "lodash/last";
import noop from "lodash/noop";
import { RealmContext } from "providers/contexts";
import {
useCallback, useEffect, useMemo, useRef,
} from "react";
import Observation from "realmModels/Observation";
import { useAuthenticatedInfiniteQuery, useCurrentUser } from "sharedHooks";
const { useRealm } = RealmContext;
const useInfiniteObservationsScroll = ( {
params: newInputParams,
}: Object ): Object => {
const realm = useRealm( );
const currentUser = useCurrentUser( );
const lastObservationIdRef = useRef( null );
const baseParams = {
...newInputParams,
per_page: 20,
fields: Observation.ADVANCED_MODE_LIST_FIELDS,
ttl: -1,
};
const { fields, ...queryKeyParams } = baseParams;
const queryKey = ["useInfiniteObservationsScroll", "searchObservations", queryKeyParams];
const {
data,
isFetchingNextPage,
fetchNextPage,
status,
} = useAuthenticatedInfiniteQuery(
queryKey,
async ( { pageParam }, optsWithAuth ) => {
const params = {
...baseParams,
};
let idToUse = pageParam;
if ( lastObservationIdRef.current !== null ) {
idToUse = lastObservationIdRef.current;
// reset last observation ID
lastObservationIdRef.current = null;
}
if ( idToUse ) {
params.id_below = idToUse;
} else {
params.page = 1;
}
const response = await searchObservations( params, optsWithAuth );
return response;
},
{
getNextPageParam: lastPage => last( lastPage.results )?.id,
enabled: !!( currentUser ),
// wait for user to scroll, since we're already using syncRemoteObservations
// to fetch 50 observations on mount
refetchOnMount: false,
},
);
const newlyFetchedObservations = useMemo( ( ) => {
if ( data?.pages ) {
return flatten( last( data.pages )?.results );
}
return null;
}, [data?.pages] );
useEffect( ( ) => {
if ( newlyFetchedObservations ) {
Observation.upsertRemoteObservations(
newlyFetchedObservations,
realm,
);
}
}, [realm, newlyFetchedObservations] );
const hasLocalObservations = realm?.objects( "Observation" )?.length > 0;
const fetchFromLastObservation = useCallback( async lastObservationId => {
lastObservationIdRef.current = lastObservationId;
await fetchNextPage( );
}, [fetchNextPage] );
const infiniteScrollObject = {
observations: flatten( data?.pages?.map( page => page.results ) ),
status,
firstObservationsInRealm: hasLocalObservations,
totalResults: data?.pages?.[0]?.total_results,
fetchFromLastObservation,
};
return currentUser
? {
...infiniteScrollObject,
isFetchingNextPage,
fetchNextPage,
}
: {
...infiniteScrollObject,
isFetchingNextPage: false,
fetchNextPage: noop,
};
};
export default useInfiniteObservationsScroll;