Surviving App Store Review in 2026: The React Native Rejections We Keep Seeing
A field guide to the App Store and Play Store rejections that hit React Native and Expo apps hardest in 2026 — and how to ship a build that actually gets through on the first try.

Every React Native team hits it eventually: the build is green, the PM has already told sales, and then a two-line message from App Review lands in the inbox. Guideline 4.3. Or 5.1.1. Or a Play Console warning about a permission you didn't know a library was pulling in. Here's what we've seen actually get RN and Expo apps rejected in 2026, and the fixes that stop the loop.
Why React Native apps get flagged more than native ones
App Review doesn't care what framework you used, but the pattern of rejections skews differently for RN and Expo builds. Two structural reasons:
- You inherit every native dependency your libraries pull in. A single analytics SDK can add three permissions, a tracking domain, and a background mode you never asked for.
- OTA updates change the risk model. Reviewers now assume any JS-driven app can silently change behavior post-review, and both stores have tightened language around what that JS bundle is allowed to do.
The result: RN teams get more "minimum functionality," "hidden features," and "privacy manifest" rejections than native teams building the same product. Not because the framework is worse — because the surface area is wider and less visible.
The iOS rejections that keep coming back
Guideline 4.3(a) — Spam / Minimum Functionality
This is the number one killer for smaller RN apps, especially those built on a template or a low-code wrapper. Reviewers reject apps that feel like "a website in a WebView" or a thin CRUD shell.
What actually triggers it in our experience:
- More than ~40% of screens rendered via
WebViewpointing at your marketing site - No offline behavior at all — every screen shows a spinner without network
- Sign-in wall on launch with no preview of what the app does
- Reusing the same binary across many "white label" clients without meaningful differentiation
Fix: give the app at least one genuinely native interaction (camera, haptics, notifications the user configures, on-device search), and make sure at least the first screen renders something useful offline.
Privacy manifests and required reason APIs
Since 2024 Apple has required a PrivacyInfo.xcprivacy file declaring tracking domains, collected data types, and "required reason" API usage. In 2026 this is enforced hard, and RN apps fail it constantly because a transitive dependency uses UserDefaults, NSFileManager modification dates, or systemUptime without declaring a reason.
Expo handles the app-level manifest well via config plugins, but you still need to audit third-party pods. A quick check we run before every submission:
# From the ios/ directory after pod install
grep -r "NSPrivacyAccessedAPICategory" Pods/ | \
awk -F: '{print $1}' | sort -u
# Then diff against what's declared in your app's PrivacyInfo
plutil -p ios/YourApp/PrivacyInfo.xcprivacy
If a pod uses a required-reason API and doesn't ship its own privacy manifest, you have to either declare it in yours, patch the pod, or drop the library. Apple no longer silently ignores this.
Guideline 3.1.1 — Payments outside IAP
Still a top-five rejection. The 2024 Epic ruling loosened some external-link rules in the US, but the safe default in 2026 is: any digital good consumed inside the app must use StoreKit. Common RN traps:
- A
Buy Probutton that opens Stripe Checkout in an in-app browser - "Restore purchases" that hits your own backend instead of
StoreKit - Subscription paywalls that mention pricing in a currency the store doesn't show
If you're using RevenueCat or plain react-native-iap, make sure the paywall copy matches the price the store returns at runtime, not a hardcoded string. Reviewers do check.
The Android rejections that catch RN teams off guard
Google's rejections come more from automated scans than human reviewers, which means they're both more predictable and harder to argue with.
Data safety form mismatches
Play Console cross-references your Data Safety declaration against what the app actually does at runtime. If a library sends analytics to a domain you didn't declare, you get a policy warning and eventually a removal.
Run this before every submission and reconcile the output against your Data Safety form:
# Extract every network permission and declared domain
./gradlew :app:dependencies --configuration releaseRuntimeClasspath \
> deps.txt
# Inspect the merged manifest for permissions you didn't add
cat android/app/build/intermediates/merged_manifests/release/AndroidManifest.xml \
| grep uses-permission
The usual culprits: an SDK that requests AD_ID, ACCESS_COARSE_LOCATION, or POST_NOTIFICATIONS without you noticing.
Foreground service types (Android 14+)
Every foreground service now needs a declared type, and the type must match the actual work. A React Native background audio library declaring dataSync when it's really mediaPlayback will fail Play review. Check your merged manifest, not just your own AndroidManifest.xml.
Target SDK deadlines
Google pushes the required targetSdkVersion every August. RN teams on older Expo SDKs or ejected apps with pinned versions get delisted from search for new users well before they're formally rejected. If you're not on a current Expo SDK, put the upgrade on the roadmap now, not in Q3.
The OTA update trap on both stores
Apple's guideline 3.3.1 (and Google's equivalent) explicitly allow JavaScript OTA updates, but with a condition that keeps getting tighter: the update cannot change the app's core purpose, add features not disclosed at review, or bypass native review of sensitive functionality.
In practice, what gets teams in trouble:
- Shipping a feature flag OFF at review, then flipping it ON via EAS Update the same day
- Using OTA to swap out an entire product surface (turning a fitness app into a marketplace)
- OTA-ing a paywall change that adds a purchase flow the reviewer never saw
Our rule: if a reviewer would have asked a question about it, ship it in a binary update. Use OTA for bug fixes, copy changes, and small UX tweaks. Not for anything that changes what the app is.
More on how we scope OTA in our release engineering work.
A pre-submission checklist that actually works
We run this checklist for every client build before it goes to TestFlight or Internal Testing. It's not glamorous but it cuts our first-review rejection rate to near zero.
Binary hygiene
- Version and build numbers incremented and matching between iOS and Android
- No
console.logof tokens, emails, or user IDs in release JS bundle - Source maps uploaded to Sentry (or equivalent) but not shipped in the binary
- Hermes enabled and bundle size checked against previous release
Privacy and permissions
-
PrivacyInfo.xcprivacyregenerated and reviewed againstpodmanifest scan - Play Data Safety form matches actual network calls (proxy the app for an hour and diff)
- Every
NS*UsageDescriptionstring is specific — not "we need your camera" -
AD_IDpermission removed if you don't actually use advertising ID
Review account and demo
- Demo account credentials in App Store Connect, tested from a fresh device
- Demo account has realistic data, not an empty state
- Any region-locked features have a note in the Review Notes field
- Video preview or notes for anything that requires hardware the reviewer won't have (BLE peripherals, NFC tags, printers)
Post-review discipline
- OTA channel for the reviewed build is frozen until approval
- Feature flags shipped OFF stay OFF until the binary is live for real users
- Rollout percentage starts at 10–20%, not 100%
Where we'd start
If you're mid-project and dreading your first submission: skip trying to fix everything at once. Do two things this week. First, run the pod and gradle scans above and reconcile them against your privacy declarations — that alone eliminates the most common automated rejections. Second, sit with your PM and mark every feature as either "shown at review" or "gated behind a flag," then write down which flags are safe to flip via OTA and which need a new binary. That single document has saved us more review cycles than any tooling ever has.
For teams already stuck in a rejection loop, the fastest path out is usually to reply to the reviewer with a short screen recording showing exactly what they missed, plus a fresh demo account. Long written appeals rarely work. A 30-second Loom often does.
Want a team like ours?
72Technologies builds production software for the kind of teams who actually read this blog.
Start a projectKeep reading

Background Tasks in React Native 2026: What Still Breaks on iOS and Android
Background execution is where cross-platform promises go to die. Here's what actually runs on iOS 18 and Android 15 in 2026, where Expo helps, and when you have to drop into Swift or Kotlin.

Push Notifications in React Native 2026: Expo Notifications vs FCM vs OneSignal in Production
We've shipped push on all three stacks — Expo Notifications, raw FCM/APNs, and OneSignal. Here's how they actually behave in production, including the token-refresh bugs nobody warns you about.
EAS Update in Production: What OTA Actually Ships (and What It Can't)
OTA updates are the killer feature of Expo, until they aren't. Here's what EAS Update can and cannot ship in 2026, how to roll back safely, and where we've been burned in production.
