RTK query useQuery invalidateTags on infinity scroll

Viewed 13

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,
  }
}
0 Answers
Related