All articles
Mobile DevelopmentOctober 23, 2026 7 min read

App Store Review Rejections in 2026: The React Native Patterns That Keep Getting Flagged

A field report on the App Store and Play Store rejection patterns we see hit React Native and Expo apps most often in 2026, with concrete fixes before you resubmit.

App Store Review Rejections in 2026: The React Native Patterns That Keep Getting Flagged

Shipping a React Native app in 2026 is easier than it has ever been. Getting it through review is not. Over the last twelve months we have watched Apple and Google tighten the screws on exactly the patterns Expo and RN teams love most: fast JS updates, lean MVPs, and third-party SDKs bolted on in a sprint.

This is a field report. Not a legal reading of the guidelines, just the rejection reasons we have personally argued with review boards about, and what actually got the app approved.

The rejection categories that dominate RN apps in 2026

If you look at a year of rejection emails across a portfolio of React Native and Expo apps, the same handful of guideline numbers come up again and again. The specific wording changes, but the themes are stable:

  • Apple 4.3(a) — spam / "this app is too similar to other apps you've submitted"
  • Apple 2.1 — app completeness, usually broken demo accounts or placeholder content
  • Apple 3.1.1 — in-app purchase bypass, now including subtle web-link flows
  • Apple 5.1.1(v) — account creation without an in-app delete path
  • Google's "Limited Use" policy — on sensitive permissions, especially background location and QUERY_ALL_PACKAGES
  • Google Data Safety mismatch — your declared data collection does not match what the SDKs actually do

React Native projects get flagged on these more than native projects do, and not because the framework is suspect. It is because RN teams tend to ship faster, lean on more third-party SDKs, and reuse large chunks of code across white-label builds. All three habits map directly onto the rules above.

4.3(a): the white-label trap

This is the number one reason we see RN agencies and product studios get stuck. You build a core app, then ship four customer variants with different branding, different content, and the same shell. Apple's reviewers have gotten dramatically better at spotting this in 2026, partly because they appear to be hashing bundle structure and asset layouts.

The pattern that triggers it:

  • One Expo monorepo with a shared/ package
  • Multiple app.config.ts targets with different name, slug, bundleIdentifier
  • Nearly identical screens, with content pulled from a CMS

What actually gets you unblocked

Fighting 4.3(a) with an appeal rarely works. What works is proving the apps are substantively different at the binary level, not just at the content level. Things we have done that moved the needle:

  • Ship meaningfully different feature sets per client, not just different theme tokens. If Client A has booking and Client B does not, tree-shake it out of the bundle.
  • Consolidate truly identical white-labels into a single app with in-app brand switching, and pitch that as the product.
  • Use different developer accounts when the end customer is genuinely a different legal entity, and have them sign the submission. This is the cleanest path for agency work.

If you are running a franchise or multi-location play, the single-app-with-locations model is almost always the right answer in 2026. We wrote more about structuring multi-tenant mobile products on the 72Technologies mobile services page.

2.1: the demo account and "it works on my simulator" problem

Apple reviewers test on physical devices behind what appears to be a proxied network. If your login flow depends on SMS OTP to a specific country code, or your backend rate-limits by IP, your reviewer will see a broken app and reject under 2.1.

Things that get flagged in RN apps specifically:

  • Hermes crash on first launch because a native module was linked but not initialized for the review build variant
  • Expo config plugins that work in dev but fail in a production prebuild
  • Feature flags defaulting to false for unknown users, hiding the entire app from the reviewer

A review-build checklist worth stealing

// app.config.ts
export default ({ config }) => ({
  ...config,
  extra: {
    reviewMode: process.env.APP_REVIEW === '1',
    demoUser: process.env.APP_REVIEW === '1'
      ? { email: 'review@example.com', bypassOtp: true }
      : undefined,
  },
});

Then in your auth screen:

import Constants from 'expo-constants';

const { reviewMode, demoUser } = Constants.expoConfig?.extra ?? {};

async function signIn(email: string, code: string) {
  if (reviewMode && email === demoUser?.email && code === '000000') {
    return signInAsDemo();
  }
  return normalSignIn(email, code);
}

Two rules: never ship this to a non-review build (gate it in CI by checking the environment variable only exists in the review lane), and rotate the bypass code between submissions. Reviewers do not store it, but automated scanners you do not control might.

3.1.1: in-app purchase bypass is now interpreted broadly

Since the external-link entitlement rules settled in late 2025, reviewers have been much stricter about the gray zone. In RN apps the typical failure pattern is: a user clicks "Upgrade", you open a WebBrowser.openBrowserAsync to a pricing page that happens to include a Stripe link.

Even if you never intended to bypass IAP, if that page offers a cheaper plan than what you sell through StoreKit, you will be rejected.

Safer patterns we use now:

  • Keep all consumer-facing subscription purchases inside StoreKit / Google Play Billing via a layer like RevenueCat.
  • If you must link out for a B2B tier, make the destination page clearly not consumer-oriented (SSO login, seat management, invoicing language).
  • Never show prices in-app for the web-only tier. Describe the tier, link out, and let pricing live on the web.

5.1.1(v): account deletion is not optional anymore

This has been a requirement for years, but in 2026 reviewers are testing it. If your account deletion path is "email us", you will be rejected. If it is a deep link to a web page, they will click it, and if the page requires re-login they often reject anyway.

Ship an in-app flow. Two screens, a confirm step, a call to your backend that soft-deletes immediately and hard-deletes within thirty days. Mention the thirty-day window in the UI. Done.

Google: Data Safety and sensitive permissions

Google's rejection style is different. You will not get a human arguing with you. You will get a policy violation email with a link to a form, and your release will sit in limbo.

The two most common triggers for RN apps:

Data Safety form drift

You declared that you do not collect advertising ID. Then you added a marketing SDK three sprints ago that quietly does. The Play Console's automated scan catches this on your next release. The fix is boring but critical: own a data-collection.md in your repo that lists every SDK, what it collects, and which Data Safety category it maps to. Update it in the same PR that adds or removes the SDK.

Background location and QUERY_ALL_PACKAGES

If any transitive native dependency requests ACCESS_BACKGROUND_LOCATION or QUERY_ALL_PACKAGES, you need to either justify it in the Play Console form or strip the permission. In Expo, do this in your config plugin or app.config.ts:

android: {
  permissions: ['ACCESS_FINE_LOCATION'],
  blockedPermissions: [
    'ACCESS_BACKGROUND_LOCATION',
    'QUERY_ALL_PACKAGES',
  ],
},

Then verify with aapt dump permissions on the actual AAB before you upload. We have been burned by a native module adding a permission in a point release that we did not notice until Google flagged it.

How to actually respond to a rejection

A few things we have learned about the appeals process itself:

  • Reply within 24 hours. Reviewers remember context, and your reply sits in the same thread.
  • Attach a short screen recording for anything behavioural. Loom links work. Written descriptions of UI flow almost never land.
  • Do not argue the guideline. Argue the facts of your app. Reviewers do not have authority to reinterpret policy, but they do decide whether the facts fit.
  • If you are confident you are right, escalate to the App Review Board. It is slower, but the quality of reading is noticeably higher.

For Google, skip the generic appeal and use the policy-specific contact form if one exists for your violation. Generic appeals go into a queue that moves in geological time.

Where we'd start

If you are about to submit a React Native or Expo app in the next two weeks, do three things first. Audit every native permission in your final AAB and IPA, not your source. Verify your Data Safety declarations against the actual SDK list. And run through your app once as a brand-new user on a device that has never seen your backend, with a demo account whose credentials you can paste into App Store Connect. Most rejections we see would have been caught by that last step alone.

#React Native#Expo#App Store Review#Release Ops#iOS#Android

Want a team like ours?

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

Start a project