queryQuantitySamples returns stale data while app is foregrounded.
queryQuantitySamples and queryQuantitySamplesWithAnchor return stale/outdated data while the app remains in the foreground, even when new samples are confirmed to be present in the iPhone's HealthKit store (verified via Apple Health app). The only way to get fresh data is to kill the app process and relaunch it. Even briefly backgrounding and foregrounding the app does not help - a full process termination is required.
I am not very into Swift and native modules, but I guess that this suggests the issue is on the native side - either the HKHealthStore instance or the query execution is returning cached results rather than executing a fresh HKSampleQuery against the HealthKit store each time.
Reproduction
- Wear an Apple Watch, let it collect heart rate data periodically.
- Open the app, start polling
queryQuantitySamples on a 30-second interval with a fresh time window each call:
const now = new Date();
const hourAgo = new Date(now.getTime() - 60 * 60 * 1000);
const result = await queryQuantitySamples(
'HKQuantityTypeIdentifierHeartRate',
{
limit: 550,
ascending: false,
filter: { date: { endDate: now, startDate: hourAgo } },
})
);
- Wait for new HR data to appear in Apple Health app (confirm manually).
- Observe that
queryQuantitySamples continues returning old data - the new samples are not included.
- Kill the app (swipe up from app switcher) and relaunch - the new samples now appear immediately.
Additional observations
subscribeToChanges callback does not fire while the app stays foregrounded, even after new data lands in HealthKit.
queryQuantitySamplesWithAnchor exhibits the same stale behavior - anchor-based queries also do not pick up new data.
useMostRecentQuantitySample hook also does not update.
- Briefly backgrounding the app (1 second) and returning to foreground is not sufficient - a full app kill is required.
- After kill + relaunch, the very first query returns all the "missing" samples, confirming the data was in HealthKit the entire time.
What was tried (all failed)
Attempt 1: subscribeToChanges + queryQuantitySamplesWithAnchor
const unsub = subscribeToChanges(
'HKQuantityTypeIdentifierHeartRate',
() => fetchNewSamples()
);
The subscription callback never fires while foregrounded. Anchored queries return no new samples.
Attempt 2: Polling with queryQuantitySamples + fresh dates each call
const interval = setInterval(async () => {
const now = new Date();
const hourAgo = new Date(now.getTime() - 60 * 60 * 1000);
const result = await queryQuantitySamples(
'HKQuantityTypeIdentifierHeartRate',
filter: { date: { endDate: now, startDate: hourAgo } },
);
// result still contains stale data
}, 30 * 1000);
Even with completely fresh date parameters on every call, the same old samples are returned.
Attempt 3: AppState listener to re-fetch on foreground
AppState.addEventListener('change', (nextAppState) => {
if (appState.current.match(/inactive|background/) && nextAppState === 'active') {
fetchNewSamples();
}
appState.current = nextAppState;
});
Briefly backgrounding and returning does trigger the fetch, but the query still returns stale data. Only a full process kill + relaunch works.
Attempt 4: Combining all three approaches simultaneously
All of subscribeToChanges + anchored queries + polling + AppState listener running together — still stale.
Expected behavior
queryQuantitySamples should return a fresh snapshot of the HealthKit store each time it is called, including any samples that have been written since the last call — without requiring an app restart.
Environment
@kingstinct/react-native-healthkit: 13.2.3
- React Native: 0.83.2
- Expo SDK: 55
- iOS: 26.3
- Device: iPhone 13 + Apple Watch series 8 (no eSIM on Watch, data probably syncs trough wifi)
background: true is set in Expo plugin config
queryQuantitySamples returns stale data while app is foregrounded.
queryQuantitySamples and queryQuantitySamplesWithAnchor return stale/outdated data while the app remains in the foreground, even when new samples are confirmed to be present in the iPhone's HealthKit store (verified via Apple Health app). The only way to get fresh data is to kill the app process and relaunch it. Even briefly backgrounding and foregrounding the app does not help - a full process termination is required.
I am not very into Swift and native modules, but I guess that this suggests the issue is on the native side - either the
HKHealthStoreinstance or the query execution is returning cached results rather than executing a freshHKSampleQueryagainst the HealthKit store each time.Reproduction
queryQuantitySampleson a 30-second interval with a fresh time window each call:queryQuantitySamplescontinues returning old data - the new samples are not included.Additional observations
subscribeToChangescallback does not fire while the app stays foregrounded, even after new data lands in HealthKit.queryQuantitySamplesWithAnchorexhibits the same stale behavior - anchor-based queries also do not pick up new data.useMostRecentQuantitySamplehook also does not update.What was tried (all failed)
Attempt 1:
subscribeToChanges+queryQuantitySamplesWithAnchorThe subscription callback never fires while foregrounded. Anchored queries return no new samples.
Attempt 2: Polling with
queryQuantitySamples+ fresh dates each callEven with completely fresh date parameters on every call, the same old samples are returned.
Attempt 3: AppState listener to re-fetch on foreground
Briefly backgrounding and returning does trigger the fetch, but the query still returns stale data. Only a full process kill + relaunch works.
Attempt 4: Combining all three approaches simultaneously
All of
subscribeToChanges+ anchored queries + polling + AppState listener running together — still stale.Expected behavior
queryQuantitySamplesshould return a fresh snapshot of the HealthKit store each time it is called, including any samples that have been written since the last call — without requiring an app restart.Environment
@kingstinct/react-native-healthkit: 13.2.3background: trueis set in Expo plugin config