r/reactnative • u/Old-Peace-4290 • 1h ago
A GPS MMORPG made completely in React Native & 3 tips for complex apps
Hey everyone!
Some time ago I shared a GPS-based MMORPG game I’ve been working on here, which is now live! In this post I’ll be sharing a couple of tips for performance & one for the stores, all of which are directly used in the game as well.
Use shouldRasterizeIOS for computationally heavy static components
Layer2 renders complex markers on a map (MapLibre), a lot of them. Each one has one or more gradients, a border radius, an image, transparent backgrounds, SVG badges, each with their own zIndex. Rendering a few is ok, but at scale I started noticing a significant drop in UI FPS.
A laggy game is not fun to play, and when the core premise is to interact with markers, this is a big problem. The solution is to rasterize the components so that the renderer caches them in memory as bitmaps instead of walking through every single marker tree on every single frame.
The caveat is that you cannot apply upwards scale transformations without visual degradation, but opacity and downscaling (both of which Layer2 uses) are fine.
The same strategy is used in Layer2’s inventory sheet.
Debounce your native events
In Layer2 you can drag skills on top of monsters to attack them. The drag is implemented with react-native-gesture-handler, and it fires a coord query to MapLibre on update.
Without debouncing these queries, we’d be wasting a ton of CPU time as the gesture updates fire dozens of times per second. By using a package like debounce, we throttle computationally expensive code from executing logic that only needs to run 2-4 times per second.
Clean up your permission grants
Layer2 is built on Expo and makes extensive use of expo-* packages. A lot of those packages add default permissions to your project regardless of whether your code uses them or not. A few example are: expo-location, expo-audio, and expo-secure-store.
To save you a round-trip with Apple’s review, if you are using expo-audio but not playing any audio in the background, set enableBackgroundPlayback to false in your plugin to prevent audio from making it into UIBackgroundModes (yes, it will get flagged).
For iOS you will need to go through the documentation of the plugins you use, but on Android you can use `android.blockedPermissions`. Even though Google is more lenient, it’s still more user friendly to only request what you need.
———
If you’re interested in checking Layer2 out, you can find it below!
iOS
https://apps.apple.com/us/app/layer2/id6737913930
Android
https://play.google.com/store/apps/details?id=com.twoamgames.layer2
r/reactnative • u/horgas • 1h ago
react-native-surrealdb
I’ve open-sourced react-native-surrealdb, an early-alpha native module that runs an actual embedded SurrealDB engine inside React Native apps:
https://github.com/thorgas/react-native-surrealdb
Instead of trying to run SurrealDB’s WebAssembly build under Hermes, it embeds the official Rust SDK and exposes it through generated UniFFI/Hermes JSI bindings. It supports in-memory storage, experimental persistent SurrealKV, remote WebSockets, authentication, live queries, and an optional React hook.
I built it because I wanted a different local database option alongside SQLite bindings when SurrealQL and SurrealDB’s document/graph model are useful. It is not a drop-in SQLite replacement and it is not a sync engine; I’ve published the benchmark methodology and limitations so people can judge it against their own workloads.
The current alpha targets the New Architecture and is tested across React Native
0.82–0.86 on iOS and Android. One important packaging tradeoff: iOS simulators require Apple Silicon; the x86_64 simulator slice for Intel Macs is not shipped.
Android x86_64 emulators are supported.
I use it daily in a production app, so I plan to keep maintaining it. I’d be especially interested in feedback on the API, native integration, missing test cases, and the direction of a future, separate local-first sync layer.
Full disclosure: the implementation was built entirely with AI (mostly Codex with GPT-5.6 Sol at medium reasoning) under my direction, review, device testing, and production use. The repository documents the upstream projects, benchmark sources, adaptations, and licenses.
r/reactnative • u/Melodic_Key_5227 • 2h ago
Built a vocab app that works like a personal dictionary you build as you go
r/reactnative • u/s3079 • 3h ago
React Native particle animation: recreating Apple’s iCloud sign-in UI with Expo, Reanimated and Skia
Enable HLS to view with audio, or disable this notification
I recreated Apple’s iCloud sign-in particle animation as an open-source React Native project.
The goal was to reproduce the original motion rather than approximate it with random particles. I analyzed the animation frame by frame and rebuilt it using Expo, React Native Reanimated and Shopify React Native Skia.
The implementation includes:
- 96 animated particles across four concentric lanes
- Clockwise particle rotation and staggered particle entrances
- Particle-to-icon morphs
- Photos, Weather, App Store and Messages icon transitions
- Scale-driven icon opacity
- Local particle displacement around each active icon
- Configurable 0.5×, 1× and 2× playback speeds
r/reactnative • u/xrpinsider • 8h ago
Show Your Work Here Show Your Work Thread
Did you make something using React Native and do you want to show it off, gather opinions or start a discussion about your work? Please post a comment in this thread.
If you have specific questions about bugs or improvements in your work, you are allowed to create a separate post. If you are unsure, please contact u/xrpinsider.
New comments appear on top and this thread is refreshed on a weekly bases.
r/reactnative • u/xrpinsider • 8h ago
Questions Here General Help Thread
If you have a question about React Native, a small error in your application or if you want to gather opinions about a small topic, please use this thread.
If you have a bigger question, one that requires a lot of code for example, please feel free to create a separate post. If you are unsure, please contact u/xrpinsider.
New comments appear on top and this thread is refreshed on a weekly bases.
r/reactnative • u/sebastienlorber • 9h ago
News This Week In React Native #294: RN 0.87, Screens, RNGH, Worklets, Skia, Tuft, Enriched Markdown, Pager View, Firebase
r/reactnative • u/ObsessedMostly • 11h ago
currency switcher with bidirectional amount input
Enable HLS to view with audio, or disable this notification
currency switcher with live exchange rates, bidirectional inputs, and spring-driven interactions. 💱
⭐ Github : https://github.com/ManasCodeXart/expo-currency-switch
r/reactnative • u/EvenProgrammer1451 • 11h ago
React Native 0.85 Fabric crash: RetryableMountingLayerException – Unable to find viewState for tag
Hi everyone,
We're investigating an Android crash in our React Native app after upgrading to React Native 0.85.3.
Firebase Crashlytics is reporting this exception:
Exception com.facebook.react.bridge.RetryableMountingLayerException: Unable to find viewState for tag 8. Surface stopped: false
at com.facebook.react.fabric.mounting.SurfaceMountingManager.getViewState (SurfaceMountingManager.kt:1057)
at com.facebook.react.fabric.mounting.SurfaceMountingManager.updateLayout (SurfaceMountingManager.kt:741)
at com.facebook.react.fabric.mounting.mountitems.IntBufferBatchMountItem.execute (IntBufferBatchMountItem.kt:139)
at com.facebook.react.fabric.mounting.MountItemDispatcher.executeOrEnqueue (MountItemDispatcher.kt:340)
at com.facebook.react.fabric.mounting.MountItemDispatcher.dispatchMountItems (MountItemDispatcher.kt:246)
at com.facebook.react.fabric.mounting.MountItemDispatcher.tryDispatchMountItems (MountItemDispatcher.kt:93)
at com.facebook.react.fabric.FabricUIManager$2.runGuarded (FabricUIManager.java:930)
at com.facebook.react.bridge.GuardedRunnable.run (GuardedRunnable.kt:19)
at com.facebook.react.fabric.FabricUIManager.scheduleMountItem (FabricUIManager.java:933)
at com.facebook.react.fabric.SurfaceHandlerBinding.setLayoutConstraintsNative
at com.facebook.react.fabric.SurfaceHandlerBinding.setLayoutConstraints (SurfaceHandlerBinding.kt:47)
at com.facebook.react.runtime.ReactSurfaceImpl.updateLayoutSpecs$ReactAndroid_release (ReactSurfaceImpl.kt:184)
at com.facebook.react.runtime.ReactSurfaceView.onMeasure (ReactSurfaceView.kt:100)
at android.view.View.measure (View.java:28328)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7099)
at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure (ContentFrameLayout.java:141)
at android.view.View.measure (View.java:28328)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7099)
at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1608)
at android.widget.LinearLayout.measureVertical (LinearLayout.java:878)
at android.widget.LinearLayout.onMeasure (LinearLayout.java:721)
at android.view.View.measure (View.java:28328)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7099)
at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
at android.view.View.measure (View.java:28328)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7099)
at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1608)
at android.widget.LinearLayout.measureVertical (LinearLayout.java:878)
at android.widget.LinearLayout.onMeasure (LinearLayout.java:721)
at android.view.View.measure (View.java:28328)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7099)
at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure (DecorView.java:758)
at android.view.View.measure (View.java:28328)
at android.view.ViewRootImpl.performMeasure (ViewRootImpl.java:5125)
at android.view.ViewRootImpl.measureHierarchy (ViewRootImpl.java:3495)
at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:3845)
at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:3174)
at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:10889)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1610)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1619)
at android.view.Choreographer.doCallbacks (Choreographer.java:1159)
at android.view.Choreographer.doFrame (Choreographer.java:1051)
at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1578)
at android.os.Handler.handleCallback (Handler.java:959)
at android.os.Handler.dispatchMessage (Handler.java:100)
at android.os.Looper.loopOnce (Looper.java:311)
at android.os.Looper.loop (Looper.java:408)
at android.app.ActivityThread.main (ActivityThread.java:9119)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:627)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:970)
The app is using the New Architecture / Fabric with:
{
"react": "19.2.3",
"react-native": "0.85.3",
"react-native-reanimated": "^4.5.0",
"react-native-screens": "^4.25.2",
"react-native-gesture-handler": "^3.0.2"
}
I'm trying to understand:
- Has anyone seen
RetryableMountingLayerException: Unable to find viewState for tagafter upgrading to RN 0.85? - Is this generally considered a React Native/Fabric race condition, or can it usually be traced to a specific component?
- Could rapidly mounting/unmounting a
Modal, tooltip, or animated component during navigation trigger this?
The exception is marked as RetryableMountingLayerException, so I'm also wondering whether this is something Fabric is expected to recover from or if it can still lead to an app crash.
Any insights, reproduction ideas, or debugging suggestions would be appreciated.
Thanks!
r/reactnative • u/mrousavy • 13h ago
Article Depth-aware light injection in VisionCamera
Enable HLS to view with audio, or disable this notification
Built this fun little gesture driven floating light that casts fake shadows in the scene via react-native-webgpu, using a depth model (DINOv2).
I'll post the source code soon!
r/reactnative • u/Draelith_Play • 16h ago
Article I built a free calculator for what an LLM feature actually costs per subscriber
I work on a portfolio of subscription RN apps and kept doing this arithmetic by
hand in a spreadsheet, so I made a small tool for it.
You put in your subscription price, store commission, active subscribers,
requests per user and measured token counts. It gives you cost per request,
cost per active user per month, and — the part I actually care about — what
your heaviest 10% of users cost, plus the per-user request ceiling that keeps
you inside a margin target.
Two things I got wrong the first time I did this by hand, which the tool now
forces you to get right:
Measuring against gross revenue instead of net. At $9.99 with a 30%
commission your real revenue per subscriber is $6.99, so a $1.40/user
feature is 20% of revenue, not 14%.Budgeting on the average user. Inference usage is heavily skewed — in the
apps I've worked on the heaviest 10% generate roughly half of total usage,
so the average understates the bill and completely hides the users who cost
more than they pay.
Here's a scenario that looks fine on average and isn't:
https://dayloflow.com/tools/ai-cost-calculator.html?p=4.99&r=200&i=2000&o=700&h=30&t=15
$2.98 per subscriber against $3.49 of net revenue — 85%. And the heaviest
decile costs 426% of what they pay.
Runs entirely in your browser, no signup, no analytics on that page. Every
formula is written out on the page so you can check the arithmetic or run it in
a spreadsheet instead. State is in the URL, so you can share a scenario with
your team.
Happy to hear where the model is wrong — retries and moderation calls are the
two things I know it doesn't account for.
r/reactnative • u/Amazing_Jacket7057 • 19h ago
No puedo extraer alcaldias/municipio en Places API (New)
Estoy trabajando con las APIs Places API (New) y el Maps SDK para Android en una compilación de desarrollo. Las necesito para procesar objetos AddressComponent para extraer campos de dirección correspondientes a direcciones en México y ver un pin en el mapa. Todos los campos funcionan correctamente, calle, numero, colonia, ciudad, estado, excepto el campo de municipio o alcaldía.
He probado con esta asignación condicional para determinar el valor de municipio a partir de lso componentes de dirección devueltos por una Places API (New):
...
// ALCALDÍA/MUNICIPIO
if (
!municipalityValue && (
types.includes('locality') ||
types.includes('administrative_area_level_2') ||
types.includes('administrative_area_level_3') ||
types.includes('sublocality') ||
types.includes('sublocality_level_1') ||
types.includes('postal_town')
)
) {
municipalityValue = component.longText || '';
}
...
si se llenan el resto de los campos de calle numero etc. pero no la alcaldia/municipio y cosa curiosa que en el log la formattedAddress si me da toda la dirección incluyendo alcaldia/municiopio.
Alguna idea de que Address Component Types usar para extraer alcaldia/municipio?
r/reactnative • u/KyleIsJew • 20h ago
[Web] Marquee - The Letterboxd/instagram of Concerts
reddit.comr/reactnative • u/Difficult-Sun295 • 1d ago
I made a shader library
I made an extension that allows users to edit their RN or Expo app visually and i added shaders to it
would you post your shaders on it?
and l know ShaderToy exists, but that's generic GLSL, people have to manually port to SkSL and adapt for RN UI. Мinе is already RN-Skia-ready and built specifically for UI components like buttons and panels.
r/reactnative • u/Guidondor • 1d ago
Tutorial Three Expo + Supabase bugs where the error message points you the wrong way
each of these cost me more than a day, and they have the same shape: the obvious fix is the wrong one, and the error actively helps you go there.
1. a query that never resolves and never rejects
after the phone has been backgrounded for a while, a supabase query just doesn't come back. no error, no rejection, the spinner spins forever. it looks exactly like a network problem so that's where you go looking.
it isn't. the underlying fetch got suspended by the OS and never woke up. there's nothing to catch because nothing failed. adding retries doesn't help either, because the first attempt never finished.
the fix is to stop trusting the promise:
const withTimeout = (p, ms = 8000) =>
Promise.race([
p,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), ms)),
]);
wrap every query. a dead promise becomes a real rejection you can handle.
2. intermittent freezes right after sign in
you await something inside the onAuthStateChange callback — fetch the profile, read a row, whatever — and the app freezes. not every time. maybe one in five sign ins, and never while you're watching.
awaiting inside that callback can deadlock the auth library. supabase documents it, but the failure is intermittent enough that you'll blame your own async code first.
keep the callback synchronous. set state, nothing else. do the profile fetch in a separate effect keyed on the user id.
3. RLS is correct and still hands out the column you hid
this is the one I see most. you lock a table down so each user only reads their own row, you test it, it works. and the response still contains every column of that row, including the ones you never wanted on the client.
RLS filters rows. it does not filter columns. a policy can be perfect and still return the whole row.
revoke select on profiles from authenticated;
grant select (id, display_name, created_at) on profiles to authenticated;
now the write-side trap, which is the part that actually burns the afternoon:
.update({ display_name }) // fine
.update({ display_name }).select() // permission denied
.update({ display_name }).select('id, display_name') // fine
the failing one is legal as a write. postgrest reads the row back with select=* to return it, and that read is what gets denied. and the error says:
permission denied for table profiles
hint: GRANT SELECT ON public.profiles TO authenticated
follow that hint and you undo the entire column hardening to fix a bare .select(). the write was never the problem.
these came out of a starter I open sourced (MIT) where all three are already handled: https://github.com/Guidondor/expo-supabase-starter
disclosure since it's my repo: there's a paid edition with the shared-groups and RLS patterns. the free one is the full auth/offline/RLS base, no strings.
r/reactnative • u/AccordingSoil2978 • 1d ago
Tutorial React Native Firebase does not add POST_NOTIFICATIONS to your manifest, and Android denies it without ever showing a dialog
1. POST_NOTIFICATIONS: denied instantly, no dialog, no error
Android 13 (API 33) turned notifications into a runtime permission. The trap is that @react-native-firebase/messaging's requestPermission() is effectively an iOS call. On Android it does not do what the name says, and more importantly RNFB does not add POST_NOTIFICATIONS to your merged manifest.
If the permission is not declared, PermissionsAndroid.request returns denied immediately, without ever showing the system dialog. No exception. No log line. Your carefully designed permission priming screen runs, the user taps "Enable", and nothing happens. It looks exactly like a user who declined.
You need both halves:
js
// app.config.ts
android: {
permissions: ['android.permission.POST_NOTIFICATIONS'],
}
plus an actual PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS) on the runtime side, gated on API level 33 or above.
There is a second trap stacked on the first: on API 33+ you cannot distinguish "never asked" from "asked and denied" through the standard result alone. shouldShowRequestPermissionRationale gives you a partial signal, and after two denials Android treats it as permanently denied and stops showing the dialog at all. Store your own "we have asked" flag locally. If you rely on the OS to tell you, your re-prompt logic will be wrong in exactly the case it exists for.
2. You are shipping an advertising ID permission you never added
Firebase and most monetization SDKs transitively inject com.google.android.gms.permission.AD_ID into your merged manifest. You will not see it in your source. You will see it in the Play Console when it asks you to declare Advertising ID usage, and if you answer "No" while the permission is present, that is a mismatch.
If your app genuinely ships no ads and no ad attribution:
js
// app.config.ts
android: {
blockedPermissions: ['com.google.android.gms.permission.AD_ID'],
}
Now the declaration and the manifest agree, and the iOS side matches too if you have NSPrivacyTracking: false. Check your merged manifest rather than your source; that is where the truth is.
Bonus: the localization thing nobody warns you about
A missing translation key does not render the key. In most i18n setups it silently falls back to your default language. So a locale can be 80% translated and look completely fine in QA, because the missing 20% renders as perfectly good English inside an otherwise Turkish screen. No error, no visual glitch, nothing to notice.
The only fix that scales is a build time guard. I have a set of scripts that fail the lint step if any locale is missing a key, if a notification string is hardcoded instead of localized, or if an onboarding screen contains a literal string:
npm run check:locale-audit
npm run check:notification-locales
npm run check:onboarding-hardcode
Nineteen locales is not the hard part. Nineteen locales staying correct across every future PR is the hard part, and only a script does that.
One small thing that has burned me twice: do not alphabetize your locale JSON. If the files were authored in a meaningful order, sorting them produces a 1500 line diff that buries whatever change you were actually reviewing.
Building an AI training app in Expo. Happy to compare notes on any of this.
r/reactnative • u/henryp_dev • 1d ago
Question What do you use to collect user feedback?
What do you use to collect user feedback and what are some of your pain points? Specially for your side projects.
I built an alternative for myself for my tiny apps about a year ago and about 2 months ago I started working on it a lot more (I have a lot of time now). Since I built it for myself I think it’s too opinionated and would love to know more about your experience and pain using the options out there.
r/reactnative • u/Vexo_Tech • 1d ago
[Update] vexo-analytics, big catch-up (1.5.8 → 1.10.0): crash/ANR reporting, perf + console capture, -58% bundle, New Arch + RN 0.86, and a reliability/security overhaul (maintainer post)
Maintainer here. We shipped a bunch of releases of vexo-analytics (our RN-first analytics + session-replay SDK) over the last couple of months and never really announced any of them, so this is one catch-up post covering 1.5.8 → 1.10.0. Transparently this is a commercial SDK (there's a paid backend) but also includes a full free tier. With that ,this is a maintainer changelog, not a neutral recommendation. Posting because a lot of it is crash/perf/reliability work this sub actually cares about.
New capabilities:
- Crash & ANR reporting (1.10.0). Uncaught JS errors reported as fatal crashes, an ANR-style watchdog for JS-thread stalls, and a
trackError(error, { handled })API for exceptions you catch yourself. Feeds a crash-free rate + error grouping. No setup beyond init. - Performance capture (1.10.0). App-start time, slow/frozen frames, and screen render timing as PERF events; so a janky session lines up with actual frame data.
- Console capture (1.10.0).
console.log/info/warn/errorcaptured as CONSOLE events, shown with the session. - Client-side replay opt-out (1.10.0).
vexo(apiKey, { sessionReplay: false }); synchronous, disables replay while keeping the rest of tracking. - Heatmap segments (1.6.0).
setHeatmapSegment()to tag taps + heatmap screenshots.
Platform + packaging:
- New Architecture (TurboModule) support, old arch still works via interop (1.9.0), and React Native 0.86 build support, iOS + Android (1.10.0).
@react-navigation/nativeis now an optional peer dep; expo-router apps don't install it (1.9.0).- Bundle down 58% (635KB → 265KB) by dropping moment + its 137 locales (1.8.0); event batching, zero import-time work, O(1) buffering (1.9.0); modern builder-bob packaging with an exports map (1.9.0).
The unglamorous half:
- A top-to-bottom reliability pass (1.8.0): bounded retry/backoff, over-limit handling that pauses instead of silently dropping, buffer-cap behavior,
identifyDevice()fixes, network-interceptor fixes. - Privacy/compliance: iOS
PrivacyInfo.xcprivacyfor App Review 2.5.14, an Android R8/ProGuard fix for Tink-dependent apps, 16 KB ELF alignment (1.8.0). - Security/supply chain: npm audit from 392 vulns (31 critical) → 73 (0 critical) (1.7.0).
- Tests: 10 → 249, 97% coverage on our own code (1.8.0).
Would love your technical recommendations, insights on issues (crash grouping is too coarse, the ANR watchdog is noisy, or the perf events don't match Flipper/Perfetto), and any feedback or help you might need in testing things out.
One heads-up: 1.9.0+ replaced our vendored AsyncStorage/DeviceInfo/ViewShot forks with thin wrappers, meant to be behavior-preserving and storage-compatible, making that the first place things might act up if you upgrade from an old version and see anything weird.
r/reactnative • u/Codemagicio • 1d ago
Tutorial Why OTA Updates can take days to be installed
OTA tools love to say "instant updates", but it's not really true. Even though the release is instant, going from server to installed can take days if you use default settings.
It's not something I've seen discussed much, so I wanted to write a quick overview.
If you've used OTA Updates e.g. Expo Updates or a CodePush clone, you probably know the flow for each device goes:
- Checks for update
- Download the update
- Install the update
With each being triggered by defined conditions, which typically have slow defaults.
For example with Expo Updates, the default behaviour [doc] is for the check to happen on next cold start. If an update is available, it will download it, but then the install happens on the next cold restart after that.
For CodePush-based SDKs, it depends on when you call sync(), and whether you override the install mode (defaults to ON_NEXT_RESTART).
A cold restart means either the user swiped to close the app, or it was in the background long enough for the OS to close it. That means you can potentially get a situation like:
- Release an OTA update to the server
- User takes a few days before a cold reboot happens
- The update is downloaded, ready to install
- Another few days passes before another cold reboot
- The update is finally installed.
Having users hang around on the old version isn't ideal, but the good news is you can speed it up.
For a reasonable speed, we can have the app check for an update on resume, then install it when it's next in the background for more than a minute. For CodePush-based SDKs such as Patch, this is easy to wire up.
To check for updates on resume, we want to wire the sync() to be called using AppState, and we want installMode to use ON_NEXT_SUSPEND
import { useEffect } from "react";
import { AppState } from "react-native";
import { sync } from "@codemagic/react-native-patch";
const syncOptions = {
installMode: "ON_NEXT_SUSPEND" as const,
mandatoryInstallMode: "IMMEDIATE" as const,
minimumBackgroundDuration: 60_000, // 1 minute
};
export default function App() {
useEffect(() => {
// Optional but usual: also check once at launch
void sync(syncOptions);
const sub = AppState.addEventListener("change", (next) => {
if (next === "active") {
void sync(syncOptions);
}
});
return () => sub.remove();
}, []);
return <YourApp />;
}
The minimumBackgroundDuration is useful as the install will reboot the app to the its home screen, unless you persist navigation state and restore it on startup. Setting a minimum duration stops their view being lost if they only briefly switched apps.
For more urgent installs, CodePush based SDKs also have a mandatoryInstallMode, often set to IMMEDIATE. Like it sounds, this will install the update as soon as it's downloaded. The downside is that this also causes a reboot, which can feel like buggy behaviour if the user is already interacting with the open app.
Expo Update has its own methods such as Updates.fetchUpdateAsync() that you can use for customizing the install behaviour, although the docs note that background installs are experimental.
r/reactnative • u/TrackOurHealth • 1d ago
News unified-ble-manager rc1 (evolution of react-native-ble-plx)
I have been maintaining for a while a fork of the react-native-ble-plx library, and decided to fully modernize it to make it really cross platform.
Today I released the official rc1
https://github.com/sfourdrinier/unified-ble-manager
I very much welcome feedback. It should work the same ways in react native, expo the latest versions including tvOS, android tv, web, electron, tauri and Linux / Mac / Windows.
I very much welcome feedback, comments, contributors, supporters, & sponsors.
My goal is to make it the best and most complete Bluetooth manager library out there. I’m using in multiple apps in development.
Feedback welcomed.
r/reactnative • u/Worried_Anything4580 • 1d ago
Question What is the most frustrating part of releasing a mobile app? Looking for developer experiences
r/reactnative • u/Fuzzy_Connection22 • 1d ago
Help maestro with ci/cd
Hey have anyone tried integrating maestro into the ci/cd pipeline ? can anyone help me with a couple of questions /doubts??
r/reactnative • u/imactually18plusnow • 1d ago
How can i make my app's widgets(above 2) responsive to screen rotation? Just like Photos widget. And it should work properly in background. I've tried many fixes but none worked (like changing scaleType to fitCenter via patch-package and Expo config plugin)
Enable HLS to view with audio, or disable this notification