All articles
Mobile DevelopmentAugust 6, 2026 7 min read

App Store Review Rejections for React Native Apps in 2026: The Patterns We Keep Seeing

A field guide to the App Store and Play Store rejection reasons that hit React Native and Expo apps hardest in 2026 — and how to ship past them without burning a week of review time.

Every mobile team eventually learns that shipping code is the easy part. The hard part is convincing two reviewers — one at Apple, one at Google — that your React Native app deserves to exist. In 2026, the rejection patterns have shifted enough that yesterday's checklist is no longer enough.

This is a field guide based on what we keep seeing across React Native and Expo submissions this year: what gets flagged, why, and what actually clears review on the resubmit.

The 2026 rejection landscape, briefly

Two things changed the shape of app review over the last eighteen months. First, Apple's automated pre-checks got noticeably more aggressive around privacy manifests and third-party SDK declarations. Second, Google Play's real-device testing requirement for new personal developer accounts pushed a lot of indie React Native apps into a longer, stranger onboarding.

The practical result: fewer rejections for crashes, more rejections for metadata, privacy, and payment flow issues. Which is bad news for React Native teams, because those are exactly the areas where the JavaScript layer hides the truth from you.

Privacy manifests and the SDK list you didn't write

Apple's PrivacyInfo.xcprivacy requirement is the single most common rejection trigger we see on iOS in 2026. Expo's prebuild handles the app-level manifest reasonably well, but the trap is transitive: every native dependency needs its own manifest, and Apple checks.

If you're using a library that hasn't been updated in a year, there's a real chance it's missing one. The rejection email will name the SDK. The fix is either updating, forking, or replacing.

How to audit before you submit

Run this against your built .xcarchive to see which frameworks are missing manifests:

find /path/to/YourApp.xcarchive -name "*.framework" -type d | while read fw; do
  name=$(basename "$fw" .framework)
  if [ ! -f "$fw/PrivacyInfo.xcprivacy" ]; then
    echo "MISSING: $name"
  fi
done

Apple's list of SDKs that require a manifest and a signature is public and has grown. If you're pulling in analytics, ads, crash reporting, or anything that touches the file system or user defaults, assume it's on the list until you've checked.

The other half of this is the required reason API declarations. NSUserDefaults, stat, fopen, mach_absolute_time — all of them need a reason code in your manifest. React Native itself declares its own reasons in recent versions, but any older bridging library might not. Rejection reads: "missing an approved reason for the declared use of the API."

Account deletion: still catching people out

Apple's Guideline 5.1.1(v) — account deletion inside the app — has been in force since 2022, but we still see React Native apps rejected for it every month. The pattern is almost always the same: the app has sign-up, has sign-in with Apple, has a settings screen, but the delete flow either doesn't exist or is a Linking.openURL to a web page.

A web link is not sufficient. The deletion has to be initiated inside the app. You can then complete it server-side, but the user must be able to start it without leaving.

If your app supports Sign in with Apple, you also need to revoke the Apple token on deletion. This is the part most teams miss:

// After you've confirmed the user wants to delete
const { authorizationCode } = await AppleAuthentication.refreshAsync({
  user: appleUserId,
});

await fetch('https://your.api/account/delete', {
  method: 'POST',
  headers: { Authorization: `Bearer ${sessionToken}` },
  body: JSON.stringify({ appleAuthCode: authorizationCode }),
});
// Server exchanges the code and calls Apple's revoke endpoint.

Skip the revoke and you'll pass review, but you'll fail Apple's periodic audits later.

In-app purchase geometry

We wrote a longer piece on receipts recently, so I'll keep this narrow. The two rejection patterns that dominate in 2026:

  1. Digital goods routed through Stripe or a web checkout. Still not allowed. The External Link Entitlement in the US and EU has narrow, specific requirements — a plain "Buy on our website" button won't clear review. If you're a reader app under 3.1.3(a), the entitlement is different again.
  2. Missing restore purchases. Every app with non-consumable IAP or subscriptions needs a visible "Restore Purchases" button. Buried three screens deep in settings counts, but only just. Reviewers will look for it.

On Android, the equivalent trap is using Google Play Billing for something Google considers off-platform (physical goods, one-off services) and getting flagged during review. The line is drawn differently than on iOS and it moves.

Permissions you request but never use

Both stores now cross-reference your declared permissions against actual runtime behaviour. If your Info.plist declares NSLocationWhenInUseUsageDescription because a library you removed six months ago used to need it, expect a rejection asking you to justify the request or remove it.

Expo's config plugins make this easier to control than bare React Native, because your permissions live in app.json and get regenerated on each prebuild. Still, audit them:

# From project root
plutil -p ios/YourApp/Info.plist | grep -i usage

On Android, look at the merged manifest, not just your source:

cd android && ./gradlew :app:processReleaseManifest
cat app/build/intermediates/merged_manifests/release/AndroidManifest.xml | grep uses-permission

You will almost always find one you don't need. A dependency added it, and it stuck.

App Tracking Transparency: the copy, not the code

ATT rejections in 2026 are almost never about missing the prompt. They're about the wording. Apple wants the NSUserTrackingUsageDescription string to describe what you actually do with the tracking data — vague strings like "to improve your experience" now bounce reliably.

A string that clears review looks more like: "Used to measure the effectiveness of ads that brought you here and to show you more relevant offers from our partners." Specific, honest, boring.

The secondary trap: showing your own custom pre-prompt that pressures the user before the system dialog. Apple's rules on this tightened, and a pre-prompt that says "tap Allow on the next screen" now counts as coercion. A pre-prompt that explains context is still fine.

OTA updates and the review-time build

EAS Update and CodePush both let you ship JS bundles outside review. Apple's policy hasn't changed in principle — you can't materially alter the app's behaviour or features via OTA — but enforcement got sharper in 2026 after a couple of high-profile abuse cases.

Two specific things to watch:

  • Feature flags that unlock major functionality post-review. If a reviewer sees a stripped-down app and your production users see a different one, that's a rejection waiting to happen. The safer pattern is to have the feature present, disabled behind server config, and toggled on at your own pace.
  • OTA channel confusion at review time. If your review build points at a channel that's ahead of what the reviewer sees on first launch, you can end up shipping code the reviewer never approved. Pin the review build to a specific update ID, or disable OTA for the review build entirely and re-enable in the next release.

We covered rollback strategy in more depth over on the blog.

Metadata rejections that feel unfair

A growing share of rejections have nothing to do with the binary. They're about screenshots, subtitle, keywords, or the promotional text:

  • Screenshots that show features not in the current build (common when you shipped a smaller MVP than you designed).
  • Screenshots with device frames from a competitor's OS.
  • Keywords that name competitors — this used to be a warning, it's now a straight rejection.
  • A subtitle that duplicates the app name.
  • Support URLs that 404 or redirect to a marketing homepage without support content.

None of these require a rebuild. They're 20-minute fixes that cost you 48 hours of review time. Check them before you hit submit, not after.

The Play Store's quieter rejections

Google's rejections are less theatrical than Apple's but often harder to resolve because they arrive as policy violations rather than review notes. The 2026 patterns:

  • Data safety form mismatches. Your declared data collection has to line up with what the Play Console's automated scanner sees your app doing. React Native apps get flagged when a library sends analytics you didn't declare.
  • Background location for features that don't need it. The prominent disclosure requirement now includes a video walkthrough in some categories.
  • Foreground service types. If you declare a foreground service, you must declare a type, and the type must match a runtime-approved use case. dataSync is not a catch-all any more.

Where we'd start

If you're preparing a React Native or Expo submission in 2026 and you want to minimise round-trips, we'd do three things before writing the release notes:

  1. Run a privacy manifest audit against the built archive, and update or replace any dependency that's missing one.
  2. Diff your merged Android manifest and iOS Info.plist against what the app actually does at runtime. Remove anything you can't justify in one sentence.
  3. Do a dry run of account deletion, restore purchases, and the ATT prompt on a fresh install with a reviewer's mindset — no shortcuts, no dev menu, no assumptions about state.

Most rejections we see would have been caught by an honest thirty-minute walkthrough. The teams that ship on the first submit aren't smarter; they're just more suspicious of their own build. If you want a second pair of eyes on a release, our mobile team does exactly that.

#react-native#expo#ios#android#release-ops#app-review

Want a team like ours?

72Technologies builds production software for the kind of teams who actually read this blog.

Start a project