I have a SectionList
where I want to do pull to refresh. I also have a DataContext
that provides:
fetching: boolean
, a state that indicates something is fetchingfetchedData: Data[]
, a state that contains the data stored from a fetchfetchData: () => Promise<void>
a function that fetches the data and stores it locally. It updates thefetching
state fromtrue
tofalse
- has a
useEffect
that gets triggered and executes asetFetchedData
reading from a database when thefetching
isfalse
- has a
useEffectPolling
which is a custom wrapper that provides something like a cancelablesetInterval
that can cancel a promise if it is already active. It basically runsfetchData
every minute.
My SectionList
looks like
<SectionList refreshControl={<RefreshControl refreshing={fetching} onRefresh={fetchData} /> }</SectionList>
What's happening is the refresh icon is appearing every minute (which I expected from my code). However, what I want is to somehow not show it when it is being updated in the background. However, still show it if I pulled to refresh.
The code for the DataContext
is something like following: I skipped some of the cleanup code and creation of some cancelable promises for brevity
export function DataContextProvider({children}) { const [fetching, setFetching] = useState<boolean>(true); const [fetchedData, setFetchedData] = useState<Data[]>([]); useEffect(()=>{ (async () => { // fetch remote and store to local db await service.fetchAndStore() setFetching(false); })() }, []); useEffect(()=>{ if (fetching) { console.log("still fetching don't do anything") return () => {} } const cancelablePromise = cancelable(async () => { // updates the state with the stored data setFetchedData(await service.getStoredData()); })()); return () => cancelablePromise.cancel(); }, [fetching]); const fetchData = async () => { setFetching(true) await service.fetchAndStore() setFetching(false) } // This is a wrapper that executes something every few seconds something like // a smarter setInterval. I don't think it is relevant to the question. useEffectPolling(fetchData, 60000); return <DataContext.Provider value={{ fetching, fetchData, fetchedData, }}> {children}</DataContext.Provider>}
My guess, though I am not sure if it is a good idea is to have a second state called backgroundFetch
and use that as an internal state. But I am concerned about the rerendering performance.