Skip to main content

14.7.18 - useIAP Hook Improvements

· 3 min read
Hyo
React Native IAP Maintainer

This release improves the useIAP hook with stable function references, proper option forwarding, and a new reconnect method for manual connection retry.

Stable restorePurchases Reference (#3172)

Problem

restorePurchases was defined as an inline async function in the return object, creating a new function reference on every render. This caused unnecessary re-renders in components that depended on it and broke useCallback/useMemo memoization chains.

Fix

Extracted restorePurchases into a proper useCallback with a stable reference. It also now calls syncIOS() directly instead of going through restorePurchasesTopLevel(), eliminating a redundant getAvailablePurchases network request.

// Before: new function every render + double network call
restorePurchases: async () => {
await restorePurchasesTopLevel(); // calls getAvailablePurchases internally
await getAvailablePurchasesInternal(); // calls it again
}

// After: stable reference + single network call
const restorePurchases = useCallback(async () => {
if (Platform.OS === 'ios') await syncIOS();
await getAvailablePurchasesInternal(options);
}, [getAvailablePurchasesInternal, invokeOnError]);

Forward PurchaseOptions in Hook Methods (#3173)

Problem

The useIAP hook's getAvailablePurchases and restorePurchases methods didn't accept or forward PurchaseOptions. Users couldn't control iOS-specific options (alsoPublishToEventListenerIOS, onlyIncludeActiveItemsIOS) or Android options (includeSuspendedAndroid) through the hook API.

Fix

Both methods now accept an optional PurchaseOptions parameter and forward it to the underlying API:

const { getAvailablePurchases, restorePurchases } = useIAP();

// Now you can pass options through the hook
await getAvailablePurchases({
onlyIncludeActiveItemsIOS: false,
includeSuspendedAndroid: true,
});

await restorePurchases({
alsoPublishToEventListenerIOS: true,
});

The Android Nitro calls also now correctly forward includeSuspendedAndroid to the native layer.

New reconnect Method (#3174)

Problem

When the initial store connection fails (e.g., Play Store not ready at mount time on Android, or transient network issues), users had no way to retry through the hook — they had to unmount and remount the component.

Fix

Added a reconnect() method that manually retries the store connection:

const { connected, reconnect } = useIAP({
onError: (error) => {
console.warn('Connection failed:', error);
},
});

// Retry connection after failure
const handleRetry = async () => {
const success = await reconnect();
if (success) {
console.log('Reconnected!');
}
};

Key implementation details:

  • Shared helpersbuildAndroidConfig, registerListeners, and cleanupListeners are extracted as shared useCallback helpers used by both initIapWithSubscriptions and reconnect, ensuring consistent behavior
  • Safe state transitionsconnected is only set to true after listeners are successfully registered, preventing a "connected but no listeners" state
  • Unmount guardisMountedRef check after async initConnection prevents listener leaks if the component unmounts during reconnection
  • Full listener parity — All listeners are re-registered including userChoiceBillingAndroid

Upgrade

yarn add react-native-iap@14.7.18
# or
npm install react-native-iap@14.7.18

No breaking changes. The new reconnect method and PurchaseOptions parameter are additive.