I have this function that basically helps me implement infinite scroll everywhere. Still, I faced a problem where when I invalidate a tag related to an endless scroll tag it doesn't update the needed portion because of the offset and limit parameters.
The way I provide tags:
providesTags: (item) => item?.result
? [...item.result.departures.map(({ ID }) => ({
type: 'Departures',
id: ID,
})),
{ type: 'Departures', id: 'LIST' },
]
: [{ type: 'TransitDepartures', id: 'LIST' }],
To Invalidate tags I use invalidatesTags
The function I described
export const isValidNotEmptyArray = (array) =>
!!(array && array?.length && array?.length > 0)
const useFetchQuery = (
useGetDataListQuery,
{ offset = 0, limit = 10, ...queryParameters },
filter = () => true,
) => {
const [localOffset, setLocalOffset] = useState(offset)
const [combinedData, setCombinedData] = useState([])
const [gotWiped, setGotWiped] = useState(0)
const queryResponse = useGetDataListQuery(
{
offset: localOffset,
limit,
...queryParameters,
},
)
const { data: fetchData = { result: [], total: 0 } } = queryResponse || {}
const total = useMemo(() => fetchData.total, [fetchData])
useEffect(() => {
const value = departure ? fetchData.result.departures : fetchData.result
if (isValidNotEmptyArray(value)) {
setGotWiped(0)
if (localOffset === 0 || !localOffset) {
setCombinedData(value)
} else {
setCombinedData((previousData) => [...previousData, ...value])
}
} else if (gotWiped === 0) {
setGotWiped(1)
}
}, [fetchData])
useEffect(() => {
if (gotWiped) {
setCombinedData([])
}
}, [gotWiped])
const refresh = () => {
setLocalOffset((prev) => (prev === 0 ? null : 0))
setCombinedData([])
}
const loadMore = () => {
if (combinedData.length < total) {
setLocalOffset(combinedData.length)
}
}
return {
data: useMemo(() => combinedData.filter(filter), [combinedData, filter]),
offset: localOffset,
total:
combinedData.length > combinedData.filter(filter).length
? combinedData.filter(filter).length
: total,
loadMore,
refresh,
isLoading: queryResponse?.isLoading,
isFetching: queryResponse?.isFetching,
}
}