Skip to content

Commit 8a87968

Browse files
committed
docs: update documentation formatting and examples
1 parent 3ddc446 commit 8a87968

File tree

10 files changed

+165
-35
lines changed

10 files changed

+165
-35
lines changed

docs/docs/examples/available-purchases.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,35 @@ View the full example source:
1818

1919
- GitHub: https://github.com/hyochan/expo-iap/blob/main/example/app/available-purchases.tsx
2020

21-
## Restore Flow
21+
## Important: Hook vs Root API
22+
23+
There are two ways to use `getAvailablePurchases()`, and they behave differently:
24+
25+
| API | Return Type | How to Access Data |
26+
|-----|-------------|-------------------|
27+
| **useIAP Hook** | `Promise<void>` | Read from `availablePurchases` state after calling |
28+
| **Root API** (direct import) | `Promise<Purchase[]>` | Returned directly from the function |
29+
30+
```tsx
31+
// ✅ useIAP Hook - returns void, updates state
32+
const { getAvailablePurchases, availablePurchases } = useIAP();
33+
await getAvailablePurchases(); // returns void
34+
console.log(availablePurchases); // read from state
35+
36+
// ✅ Root API - returns data directly
37+
import { getAvailablePurchases } from 'expo-iap';
38+
const purchases = await getAvailablePurchases(); // returns Purchase[]
39+
```
40+
41+
## Restore Flow (Using Hook)
2242

2343
- Ensure the store connection is active (handled by `useIAP`)
2444
- Call both `getAvailablePurchases()` and `getActiveSubscriptions()`
45+
- Read restored items from hook state (`availablePurchases`, `activeSubscriptions`)
2546
- Validate on your server and grant entitlements
2647

2748
```tsx
28-
import React from 'react';
49+
import React, {useCallback} from 'react';
2950
import {Alert} from 'react-native';
3051
import {useIAP} from 'expo-iap';
3152

@@ -34,26 +55,30 @@ export default function AvailablePurchasesScreen() {
3455
connected,
3556
getAvailablePurchases,
3657
getActiveSubscriptions,
58+
availablePurchases,
3759
activeSubscriptions,
3860
finishTransaction,
3961
} = useIAP();
4062

41-
const restore = async () => {
63+
const restore = useCallback(async () => {
4264
if (!connected) return;
43-
const [purchases] = await Promise.all([
65+
66+
// Both methods return void and update internal state
67+
await Promise.all([
4468
getAvailablePurchases(),
4569
getActiveSubscriptions(),
4670
]);
4771

48-
for (const p of purchases) {
72+
// Read from hook state (availablePurchases is now updated)
73+
for (const p of availablePurchases) {
4974
// TODO: validate on your backend first
5075
// await grantEntitlement(p)
5176
// Non-consumables and subscriptions typically don't require consumption
5277
await finishTransaction({purchase: p, isConsumable: false});
5378
}
5479

55-
Alert.alert('Restored', `Restored ${purchases.length} purchases`);
56-
};
80+
Alert.alert('Restored', `Restored ${availablePurchases.length} purchases`);
81+
}, [connected, getAvailablePurchases, getActiveSubscriptions, availablePurchases, finishTransaction]);
5782

5883
return null; // Render your UI and call restore() from a button
5984
}

docs/docs/guides/troubleshooting.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ const {finishTransaction} = useIAP({
158158
**Important - Transaction Acknowledgment Requirements**:
159159
160160
- **iOS**: Unfinished transactions remain in the queue indefinitely until `finishTransaction` is called
161+
- **Note**: Transactions do NOT auto-finish by default. You must explicitly call `finishTransaction` after validating the purchase. Only set `andDangerouslyFinishTransactionAutomatically: true` if you understand the security implications (skipping server-side validation).
161162
- **Android**: Purchases must be acknowledged within **3 days (72 hours)** or they will be **automatically refunded**
162163
- For consumable products: Use `finishTransaction({purchase, isConsumable: true})`
163164
- For non-consumables/subscriptions: Use `finishTransaction({purchase})` or `finishTransaction({purchase, isConsumable: false})`

docs/versioned_docs/version-3.0/examples/available-purchases.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,35 @@ View the full example source:
1616

1717
- GitHub: https://github.com/hyochan/expo-iap/blob/main/example/app/available-purchases.tsx
1818

19-
## Restore Flow
19+
## Important: Hook vs Root API
20+
21+
There are two ways to use `getAvailablePurchases()`, and they behave differently:
22+
23+
| API | Return Type | How to Access Data |
24+
|-----|-------------|-------------------|
25+
| **useIAP Hook** | `Promise<void>` | Read from `availablePurchases` state after calling |
26+
| **Root API** (direct import) | `Promise<Purchase[]>` | Returned directly from the function |
27+
28+
```tsx
29+
// ✅ useIAP Hook - returns void, updates state
30+
const { getAvailablePurchases, availablePurchases } = useIAP();
31+
await getAvailablePurchases(); // returns void
32+
console.log(availablePurchases); // read from state
33+
34+
// ✅ Root API - returns data directly
35+
import { getAvailablePurchases } from 'expo-iap';
36+
const purchases = await getAvailablePurchases(); // returns Purchase[]
37+
```
38+
39+
## Restore Flow (Using Hook)
2040

2141
- Ensure the store connection is active (handled by `useIAP`)
2242
- Call both `getAvailablePurchases()` and `getActiveSubscriptions()`
43+
- Read restored items from hook state (`availablePurchases`, `activeSubscriptions`)
2344
- Validate on your server and grant entitlements
2445

2546
```tsx
26-
import React from 'react';
47+
import React, {useCallback} from 'react';
2748
import {Alert} from 'react-native';
2849
import {useIAP} from 'expo-iap';
2950

@@ -32,26 +53,30 @@ export default function AvailablePurchasesScreen() {
3253
connected,
3354
getAvailablePurchases,
3455
getActiveSubscriptions,
56+
availablePurchases,
3557
activeSubscriptions,
3658
finishTransaction,
3759
} = useIAP();
3860

39-
const restore = async () => {
61+
const restore = useCallback(async () => {
4062
if (!connected) return;
41-
const [purchases] = await Promise.all([
63+
64+
// Both methods return void and update internal state
65+
await Promise.all([
4266
getAvailablePurchases(),
4367
getActiveSubscriptions(),
4468
]);
4569

46-
for (const p of purchases) {
70+
// Read from hook state (availablePurchases is now updated)
71+
for (const p of availablePurchases) {
4772
// TODO: validate on your backend first
4873
// await grantEntitlement(p)
4974
// Non-consumables and subscriptions typically don't require consumption
5075
await finishTransaction({purchase: p, isConsumable: false});
5176
}
5277

53-
Alert.alert('Restored', `Restored ${purchases.length} purchases`);
54-
};
78+
Alert.alert('Restored', `Restored ${availablePurchases.length} purchases`);
79+
}, [connected, getAvailablePurchases, getActiveSubscriptions, availablePurchases, finishTransaction]);
5580

5681
return null; // Render your UI and call restore() from a button
5782
}

docs/versioned_docs/version-3.0/guides/troubleshooting.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const handlePurchase = async (purchase) => {
161161
**Important - Transaction Acknowledgment Requirements**:
162162
163163
- **iOS**: Unfinished transactions remain in the queue indefinitely until `finishTransaction` is called
164+
- **Note**: Transactions do NOT auto-finish by default. You must explicitly call `finishTransaction` after validating the purchase. Only set `andDangerouslyFinishTransactionAutomatically: true` if you understand the security implications (skipping server-side validation).
164165
- **Android**: Purchases must be acknowledged within **3 days (72 hours)** or they will be **automatically refunded**
165166
- For consumable products: Use `finishTransaction({purchase, isConsumable: true})`
166167
- For non-consumables/subscriptions: Use `finishTransaction({purchase})` or `finishTransaction({purchase, isConsumable: false})`

docs/versioned_docs/version-3.1/examples/available-purchases.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,35 @@ View the full example source:
1818

1919
- GitHub: https://github.com/hyochan/expo-iap/blob/main/example/app/available-purchases.tsx
2020

21-
## Restore Flow
21+
## Important: Hook vs Root API
22+
23+
There are two ways to use `getAvailablePurchases()`, and they behave differently:
24+
25+
| API | Return Type | How to Access Data |
26+
|-----|-------------|-------------------|
27+
| **useIAP Hook** | `Promise<void>` | Read from `availablePurchases` state after calling |
28+
| **Root API** (direct import) | `Promise<Purchase[]>` | Returned directly from the function |
29+
30+
```tsx
31+
// ✅ useIAP Hook - returns void, updates state
32+
const { getAvailablePurchases, availablePurchases } = useIAP();
33+
await getAvailablePurchases(); // returns void
34+
console.log(availablePurchases); // read from state
35+
36+
// ✅ Root API - returns data directly
37+
import { getAvailablePurchases } from 'expo-iap';
38+
const purchases = await getAvailablePurchases(); // returns Purchase[]
39+
```
40+
41+
## Restore Flow (Using Hook)
2242

2343
- Ensure the store connection is active (handled by `useIAP`)
2444
- Call both `getAvailablePurchases()` and `getActiveSubscriptions()`
45+
- Read restored items from hook state (`availablePurchases`, `activeSubscriptions`)
2546
- Validate on your server and grant entitlements
2647

2748
```tsx
28-
import React from 'react';
49+
import React, {useCallback} from 'react';
2950
import {Alert} from 'react-native';
3051
import {useIAP} from 'expo-iap';
3152

@@ -34,26 +55,30 @@ export default function AvailablePurchasesScreen() {
3455
connected,
3556
getAvailablePurchases,
3657
getActiveSubscriptions,
58+
availablePurchases,
3759
activeSubscriptions,
3860
finishTransaction,
3961
} = useIAP();
4062

41-
const restore = async () => {
63+
const restore = useCallback(async () => {
4264
if (!connected) return;
43-
const [purchases] = await Promise.all([
65+
66+
// Both methods return void and update internal state
67+
await Promise.all([
4468
getAvailablePurchases(),
4569
getActiveSubscriptions(),
4670
]);
4771

48-
for (const p of purchases) {
72+
// Read from hook state (availablePurchases is now updated)
73+
for (const p of availablePurchases) {
4974
// TODO: validate on your backend first
5075
// await grantEntitlement(p)
5176
// Non-consumables and subscriptions typically don't require consumption
5277
await finishTransaction({purchase: p, isConsumable: false});
5378
}
5479

55-
Alert.alert('Restored', `Restored ${purchases.length} purchases`);
56-
};
80+
Alert.alert('Restored', `Restored ${availablePurchases.length} purchases`);
81+
}, [connected, getAvailablePurchases, getActiveSubscriptions, availablePurchases, finishTransaction]);
5782

5883
return null; // Render your UI and call restore() from a button
5984
}

docs/versioned_docs/version-3.1/guides/troubleshooting.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ const {finishTransaction} = useIAP({
158158
**Important - Transaction Acknowledgment Requirements**:
159159
160160
- **iOS**: Unfinished transactions remain in the queue indefinitely until `finishTransaction` is called
161+
- **Note**: Transactions do NOT auto-finish by default. You must explicitly call `finishTransaction` after validating the purchase. Only set `andDangerouslyFinishTransactionAutomatically: true` if you understand the security implications (skipping server-side validation).
161162
- **Android**: Purchases must be acknowledged within **3 days (72 hours)** or they will be **automatically refunded**
162163
- For consumable products: Use `finishTransaction({purchase, isConsumable: true})`
163164
- For non-consumables/subscriptions: Use `finishTransaction({purchase})` or `finishTransaction({purchase, isConsumable: false})`

docs/versioned_docs/version-3.2/examples/available-purchases.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,35 @@ View the full example source:
1818

1919
- GitHub: [example/app/available-purchases.tsx](https://github.com/hyochan/expo-iap/blob/main/example/app/available-purchases.tsx)
2020

21-
## Restore Flow
21+
## Important: Hook vs Root API
22+
23+
There are two ways to use `getAvailablePurchases()`, and they behave differently:
24+
25+
| API | Return Type | How to Access Data |
26+
|-----|-------------|-------------------|
27+
| **useIAP Hook** | `Promise<void>` | Read from `availablePurchases` state after calling |
28+
| **Root API** (direct import) | `Promise<Purchase[]>` | Returned directly from the function |
29+
30+
```tsx
31+
// ✅ useIAP Hook - returns void, updates state
32+
const { getAvailablePurchases, availablePurchases } = useIAP();
33+
await getAvailablePurchases(); // returns void
34+
console.log(availablePurchases); // read from state
35+
36+
// ✅ Root API - returns data directly
37+
import { getAvailablePurchases } from 'expo-iap';
38+
const purchases = await getAvailablePurchases(); // returns Purchase[]
39+
```
40+
41+
## Restore Flow (Using Hook)
2242

2343
- Ensure the store connection is active (handled by `useIAP`)
2444
- Call both `getAvailablePurchases()` and `getActiveSubscriptions()`
45+
- Read restored items from hook state (`availablePurchases`, `activeSubscriptions`)
2546
- Validate on your server and grant entitlements
2647

2748
```tsx
28-
import React from 'react';
49+
import React, {useCallback} from 'react';
2950
import {Alert} from 'react-native';
3051
import {useIAP} from 'expo-iap';
3152

@@ -34,26 +55,30 @@ export default function AvailablePurchasesScreen() {
3455
connected,
3556
getAvailablePurchases,
3657
getActiveSubscriptions,
58+
availablePurchases,
3759
activeSubscriptions,
3860
finishTransaction,
3961
} = useIAP();
4062

41-
const restore = async () => {
63+
const restore = useCallback(async () => {
4264
if (!connected) return;
43-
const [purchases] = await Promise.all([
65+
66+
// Both methods return void and update internal state
67+
await Promise.all([
4468
getAvailablePurchases(),
4569
getActiveSubscriptions(),
4670
]);
4771

48-
for (const p of purchases) {
72+
// Read from hook state (availablePurchases is now updated)
73+
for (const p of availablePurchases) {
4974
// TODO: validate on your backend first
5075
// await grantEntitlement(p)
5176
// Non-consumables and subscriptions typically don't require consumption
5277
await finishTransaction({purchase: p, isConsumable: false});
5378
}
5479

55-
Alert.alert('Restored', `Restored ${purchases.length} purchases`);
56-
};
80+
Alert.alert('Restored', `Restored ${availablePurchases.length} purchases`);
81+
}, [connected, getAvailablePurchases, getActiveSubscriptions, availablePurchases, finishTransaction]);
5782

5883
return null; // Render your UI and call restore() from a button
5984
}

docs/versioned_docs/version-3.2/guides/troubleshooting.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ const {finishTransaction} = useIAP({
158158
**Important - Transaction Acknowledgment Requirements**:
159159
160160
- **iOS**: Unfinished transactions remain in the queue indefinitely until `finishTransaction` is called
161+
- **Note**: Transactions do NOT auto-finish by default. You must explicitly call `finishTransaction` after validating the purchase. Only set `andDangerouslyFinishTransactionAutomatically: true` if you understand the security implications (skipping server-side validation).
161162
- **Android**: Purchases must be acknowledged within **3 days (72 hours)** or they will be **automatically refunded**
162163
- For consumable products: Use `finishTransaction({purchase, isConsumable: true})`
163164
- For non-consumables/subscriptions: Use `finishTransaction({purchase})` or `finishTransaction({purchase, isConsumable: false})`

0 commit comments

Comments
 (0)