Skip to content

Commit

Permalink
hotfix(codegen): hotfix useAllObjects (#5308)
Browse files Browse the repository at this point in the history
* hotfix(codegen): hotfix useAllObjects

* hotfix(codegen): hotfix useAllObjects
  • Loading branch information
Alllex202 authored and ekabardinsky committed Oct 3, 2024
1 parent 31879da commit 292c482
Showing 1 changed file with 29 additions and 33 deletions.
62 changes: 29 additions & 33 deletions packages/codegen/generate.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import dayjs from 'dayjs'
import { DocumentNode } from 'graphql'
import get from 'lodash/get'
import isFunction from 'lodash/isFunction'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'

import { getClientSideSenderInfo } from '@open-condo/codegen/utils/userId'
import { useMutation, useQuery } from '@open-condo/next/apollo'
Expand Down Expand Up @@ -381,60 +381,56 @@ export function generateReactHooks<

function useAllObjects (variables: QueryVariables, options?: QueryHookOptions<IUseObjectsQueryReturnType<GQLObject>, QueryVariables>) {
const fetchPolicy = get(options, 'fetchPolicy')
const skip = get(options, 'skip')
const { objs, count, error, loading, refetch: _refetch, fetchMore, stopPolling } = useObjects(variables, {
...options,
fetchPolicy: fetchPolicy && fetchPolicy !== 'no-cache' ? fetchPolicy : 'network-only',
})
const [data, setData] = useState(objs)
const [fetchMoreError, setFetchMoreError] = useState()
const innerLoadingRef = useRef(false)

useEffect(() => {
innerLoadingRef.current = loading
}, [loading])
const [firstPageLoaded, setFirstPageLoaded] = useState<boolean>(false)

// NOTE: returns only the first part of the data
const refetch: IRefetchType<GQLObject, QueryVariables> = useCallback((...args) => {
setData([])
// NOTE: refetch from Apollo does not immediately update loading status.
// Because of this, the resulting array contains outdated data that has already been loaded
// That's why we make our own loading indicator to prevent this from happening.
innerLoadingRef.current = true
return _refetch(...args)
}, [_refetch])

useDeepCompareEffect(() => {
setData([])
}, [variables])

useEffect(() => {
const isAllDataLoaded = objs.length === count || data.length === count
if (isAllDataLoaded || loading || error || fetchMoreError || innerLoadingRef.current) {
return
const loadMore = useCallback(async (skip) => {
try {
const { data: fetchedData } = await fetchMore({
variables: {
skip: skip,
},
})
// @ts-ignore
setData(prevData => [...prevData, ...fetchedData.objs])
} catch (error) {
setFetchMoreError(error)
}
}, [fetchMore])

if (data.length === 0) {
useEffect(() => {
if (skip) return
if (!loading && !firstPageLoaded) {
setData(objs)
return
setFirstPageLoaded(true)
}
}, [objs, loading, firstPageLoaded, skip])

fetchMore({
variables: {
skip: data.length,
},
updateQuery (previousData: IUseObjectsQueryReturnType<GQLObject>, { fetchMoreResult, variables: { skip } }) {
// Slicing is necessary because the existing data is immutable, and frozen in development.
const updatedObjs = previousData.objs.slice(0)
for (let i = 0; i < fetchMoreResult.objs.length; ++i) {
updatedObjs[skip + i] = fetchMoreResult.objs[i]
}
return { ...previousData, objs: updatedObjs, meta: fetchMoreResult.meta }
},
})
// @ts-ignore
.then(({ data }) => setData(prevData => [...prevData, ...data.objs]))
.catch(e => setFetchMoreError(e))
}, [loading, data.length])
useEffect(() => {
if (skip) return
if (!firstPageLoaded) return
if (data.length === 0) return
if (count <= data.length) return
if (error || fetchMoreError) return

loadMore(data.length)
}, [count, data.length, error, fetchMoreError, firstPageLoaded, loadMore, skip])

return {
loading,
Expand Down

0 comments on commit 292c482

Please sign in to comment.