skip to content

What common store rejection causes should you check before submitting a React Native app to the App Store and Google Play?

level: juniorimportance: should knowfreq 45%

answer

  1. what the reviewer's device actually runs
  2. a way past the login screen
  3. empty purpose strings in the template
  4. privacy manifest from pod install
  5. web wrapper, other-platform mentions

basics

~20 s

Check that the Release build works without Metro, give reviewers demo credentials, fill or remove purpose strings such as the template's empty location one, keep the privacy manifest complete, and avoid thin web wrappers and other-platform mentions.

solid answer

~40 s

The reviewer runs your **Release** build on a real device, so the first cause is a crash or blank screen that Debug never showed, often a missing embedded JS bundle. Second, a **login wall**: give working demo credentials in the review notes. Third, **permission purpose strings**: the React Native iOS template's `Info.plist` ships `NSLocationWhenInUseUsageDescription` as an empty string, which must hold a real reason if the app uses location, or be removed. Fourth, **privacy declarations**: `pod install` aggregates required-reason APIs from pods into `PrivacyInfo.xcprivacy`, so keep that file in the app target and complete. Fifth, **thin apps**: a wrapped website with little native value, or iOS metadata that mentions Android. On Google Play, meet the target API level requirement (React Native 0.87 defaults to `targetSdk` 36) and justify sensitive permissions.

go deeper

for a junior

Know the usual suspects: launch crashes in the Release build, missing demo credentials, empty permission purpose strings and store text that mentions the other platform.

for a middle

Explain why Release-only crashes happen, how React Native aggregates privacy declarations, and why the template's networking and location entries need attention.

for a senior

Turn the checklist into a pre-submission gate, test the exact submitted build on real devices, and audit permissions and declarations whenever a native library is added.

for a principal

Own review risk across both stores: who signs off metadata, how library changes trigger privacy and permission audits, and how rejections feed back into the release process.

## Why React Native apps get rejected Reviewers do not care which framework built the app; they apply the same rules to every submission. But some causes are especially common in React Native projects, because the team mostly runs Debug builds, starts from a template with placeholder values, and ships one codebase to two stores. ## The causes, and how to check each | Cause | Store | How to check before submitting | |---|---|---| | Crash or blank screen on launch | Both | Run the Release build on a device with Metro stopped | | Reviewer cannot log in | Both | Put demo credentials in the review notes | | Empty or vague permission purpose string | App Store | Read every `NS...UsageDescription` in `Info.plist` | | Missing privacy declarations | App Store | Confirm `PrivacyInfo.xcprivacy` is in the app target | | Insecure networking exceptions | App Store | Keep `NSAllowsArbitraryLoads` false | | Thin web-wrapper app | App Store | Make sure the app offers real native value | | Other platform named in metadata | App Store | Remove "Android" from iOS screenshots and text | | Target API level too old | Google Play | Check `targetSdkVersion` against Play's current requirement | | Unjustified sensitive permissions | Google Play | Remove unused permissions, declare the rest | ## Release-only crashes The reviewer's build is the **Release** configuration or release variant: JavaScript embedded in the app, production JS, optimized native code, and on Android possibly R8 shrinking. The React Native docs note that Release also removes the Dev Menu. A missing embedded bundle, a crash hidden behind `__DEV__`-only setup, or a class stripped by shrinking only shows up here. Always test the exact build you submit, on a real device, with Metro stopped. ## Permission purpose strings iOS requires a human-readable reason for each protected resource the app uses. The React Native iOS template's `Info.plist` includes: ```xml <key>NSLocationWhenInUseUsageDescription</key> <string></string> ``` An empty purpose string gives the user and the reviewer no explanation. If the app uses location, write a specific reason ("Find branches and ATMs near you"); if it does not, remove the key. Check every usage description that third-party libraries require too. ## Privacy manifest Apple requires apps to declare why they use certain **required-reason APIs**. The template ships a `PrivacyInfo.xcprivacy` listing React Native's own categories, such as file timestamps, `UserDefaults` and system boot time, and React Native's CocoaPods setup aggregates the declarations of installed pods into it during `pod install` (the `privacy_file_aggregation_enabled` option of `use_react_native!`, on by default). Keep the file in the app target and review it when you add libraries. ## Networking exceptions The template's `Info.plist` sets `NSAllowsArbitraryLoads` to `false`, with a comment warning that setting it to `true` risks rejection. It also allows local networking, which is what Metro needs in development. Add narrow per-domain exceptions if a legacy backend truly needs them, not a blanket opt-out. ## Thin or confusing apps - An app that is mostly a website in a web view, with little native functionality, risks rejection for minimum functionality. - iOS store text or screenshots that mention Android, or show Android UI, get flagged; cross-platform teams often reuse assets by mistake. - Placeholder content, broken links and unfinished screens count as incomplete apps. ## Google Play specifics - **Target API level.** Play requires new apps and updates to target a recent Android API level. React Native 0.87 defaults to `targetSdk` 36, so a current project usually passes; an app pinned to an older value may not. - **Permissions.** The React Native docs note that `INTERNET` is added by default and `SYSTEM_ALERT_WINDOW` only in debug. Remove permissions libraries add that you do not use, and declare the sensitive ones you keep. - **Store declarations**, such as the data safety form, must match what the app and its libraries actually collect. ## A pre-submission checklist 1. Install the exact Release build on a device and use every main flow with Metro stopped. 2. Prepare a demo account and note it for the reviewer. 3. Audit `Info.plist` purpose strings, networking exceptions and the privacy manifest. 4. Audit Android permissions and `targetSdkVersion`. 5. Proofread store metadata per platform.

  • Why does a React Native app that works in every Debug session still get rejected for crashing on launch?
    The reviewer runs the Release build: embedded JavaScript, production JS, optimized native code, possibly R8 shrinking on Android. A missing embedded bundle, setup code guarded by `__DEV__`, or a class stripped by shrinking only fails there. Install the exact artefact you submit on a real device, stop Metro, and exercise the main flows.
  • Where do the privacy declarations of third-party React Native libraries end up in the iOS app?
    During `pod install`, React Native's CocoaPods setup reads the required-reason API declarations of installed pods and React Native core and merges them into the app's `PrivacyInfo.xcprivacy`. That aggregation is controlled by `use_react_native!`'s `privacy_file_aggregation_enabled` option, which defaults to true. The file must be part of the app target to count.

saying these in an interview costs you the question

  • Reviewers test the Debug build, so Release-only crashes do not matter.
  • Leaving the template's empty location purpose string is harmless.
  • Setting NSAllowsArbitraryLoads to true is the normal fix for network errors.
  • Stores reject React Native apps simply because they are cross-platform.
  • Reusing Android screenshots in the App Store listing is fine.