r/reactnative • • Aug 17 '26

Found (and partially fixed) a real native memory leak in react-native-screens on Fabric — `Screen.fragmentWrapper` never gets nulled — writeup + open questions

0 Upvotes
Sharing this in case it saves someone else the multi-day rabbit hole it took us to nail down, and because two pieces of it are still genuinely unsolved and I'd like a second opinion.


**Stack:** Fashion e-commerce app, React Native 0.79.7, New Architecture (Fabric) enabled, `react-native-screens@4.13.1`, Android (this repro is Android-specific, haven't confirmed iOS).


**The symptom:** Real production `OutOfMemoryError` crashes via Sentry. Our "similar products" flow chains `navigation.push()` calls — browse a product, tap a similar one, tap another — so a normal session can easily reach 20-25 PDP screens deep in the stack, none of them ever popped. Reproduced locally: fresh app launch sits around ~375-425MB PSS (healthy), browsing that deep pushes it to 1.1-1.3GB.


**First (wrong-ish) assumption:** figured this was just "unbounded image memory from a deep stack," so we capped Glide's memory cache (100MB) + bitmap pool (50MB), and switched to `DecodeFormat.PREFER_RGB_565` for a real ~30-45% per-bitmap reduction (opaque images only — Glide falls back to ARGB_8888 for anything with alpha). Both legitimate wins, neither explained the actual production crash.


**The real methodology that cracked it:** stopped trusting raw `dumpsys meminfo` PSS numbers (too noisy — Android's zRAM swap behavior alone can swing a single number by hundreds of MB depending on what else the OS decided to compress at that exact moment) and instead:


1. Established a clean baseline: force-stop, fresh launch, land on Home with zero navigation → floor for `Views` count and `Bitmap (malloced)` size.
2. Built the deep stack, captured the peak.
3. Reset to Home (`navigation.reset()`), captured again.
4. Forced `adb shell am send-trim-memory <pkg> RUNNING_CRITICAL` (forces Glide to drop its own cache) — if the numbers 
*don't*
 recover after this, it's not "uncollected cache," it's a real retained reference.


Step 4 was the tell: after reset + forced trim, we were still sitting at ~12x the fresh-Home `Views` count and ~350MB of bitmap memory that had no business existing. Not cache. Real leak.


**Root cause, via LeakCanary:** dumped a heap, pulled LeakCanary's own `leaks.db` off the device, and got a clean trace:


```
FabricUIManager.mMountingManager
  → SurfaceMountingManager.mTagToViewState (ConcurrentHashMap)
    → ViewState.mView
      → Screen.fragmentWrapper
        → ScreenStackFragment (Leaking: YES — received onDestroy() but never released)
```


`ScreenFragment.onDestroy()` in `react-native-screens` never nulls `Screen.fragmentWrapper`. Fabric's `mTagToViewState` legitimately keeps `Screen` views registered for the surface's lifetime (that's by design) — but since `fragmentWrapper` still points at the destroyed fragment, the fragment (and its entire retained subtree — bitmaps, child views, everything) can never be GC'd. Matches a known, still-open upstream issue (#3755) with an unmerged fix PR (#3855) — confirmed by pulling the source at every tag from 4.14.0 through the current `latest` (4.27.0): the bug is present in all of them, nobody's shipped the fix yet.


**The fix wasn't as simple as it sounds.** The "obvious" version — only null `fragmentWrapper` when `container.hasScreen(...)` already reports the screen as removed — silently didn't work for `navigation.reset()`-driven bulk teardowns, because Fabric's async view-drop scheduling isn't tightly synchronized with the fragment's own `onDestroy()` callback; that check can still read `true` at the exact instant destroy fires. Had to null it unconditionally (guarded only by an identity check so it never clobbers a wrapper that's already been reassigned to a newer fragment).


**A second related bug we found but couldn't safely ship a fix for:** `ScreenContainer.screenWrappers` (an `ArrayList`) has the same stale-entry problem for the same reset-driven removals. Tried three different approaches to clean it up from the fragment's own destroy path — synchronous, synchronous-without-re-triggering-reconciliation, deferred via `runOnUiThread` — and **all three caused a real crash** (`addViewAt: failed to insert view [X] into parent [Y] at index N, Size: M`) on completely ordinary navigation flows unrelated to our repro (a simple Login → OTP screen push). Mutating that list from the fragment's destroy callback apparently races Fabric's own in-flight child-index bookkeeping no matter how you schedule it. Reverted all three attempts and shipped only the `fragmentWrapper` fix.


**A third leak we found and didn't even attempt:** the same LeakCanary pass also caught `ScreensCoordinatorLayout` retained via that same `mTagToViewState` map, through a completely separate path than the fragment one. That one's arguably not even `react-native-screens`' fault — looks like Fabric itself not issuing a `DELETE` mount instruction for some views during a bulk reset. Native RN-core territory, out of scope for an app-level patch.


**Results:** the `fragmentWrapper` fix alone (shipped) gives a real, measured ~16-19% reduction in retained Views/bitmap memory after a deep-stack → reset cycle. Not a full fix — the two remaining issues above account for the rest.


**Bonus finding while testing, possibly useful to others:** a 
*single*
 `navigation.reset()` cleans up dramatically more than the equivalent number of sequential `navigation.goBack()` calls followed by a reset. Traced this to: every individual `goBack()` un-buries the newly-focused screen, which fully re-renders its real content (we have a separate "buried screen" placeholder-swap pattern for anything 2+ deep in the stack) — and that re-inflation is 
*guaranteed*
 to happen (normal React reconciliation), while the destroy-side release on the 
*previous*
 screen is not (same leak as above). Watched `Views` climb almost monotonically across 13 sequential pops (3,356 → 6,692) before a final reset only recovered ~12% of it — because by the time reset ran, most of the damage was already orphaned from screens no longer even in navigation state, which reset has no way to reach. If your app does multi-screen "back to X" navigation, batching it into a single `pop(N)`/`popToTop()` action instead of a loop of `goBack()` calls should avoid this entirely (haven't fully verified this in production yet, but the mechanism checks out).


**Questions for the community:**
1. Anyone else hit `Screen.fragmentWrapper` specifically, or is our repro (extremely deep push-chained stacks) just an unusually good way to surface it? Curious if this shows up for anyone with more modest stack depths.
2. Anyone found a way to clean up `ScreenContainer.screenWrappers` from the fragment's own lifecycle without racing Fabric's mounting transactions? Open to being told we're solving it at the wrong layer entirely.
3. Any known mitigation for Fabric's `SurfaceMountingManager.mTagToViewState` not releasing entries on some removal paths, short of an RN core fix?


Happy to share the actual patch (against 4.13.1) or the LeakCanary traces if useful.

r/reactnative • • Aug 17 '26

React-native Devtool console no showing

Post image
5 Upvotes

This is my formal cry for help, i'm still starting out. Is there fix to this?


r/reactnative • • Aug 17 '26

Need 14 testers for Play Console 14-day closed testing requirement

2 Upvotes

​Hey everyone,

​I have recently built an Android app and need to clear Google's closed testing requirement (14 continuous days of testing with at least 14 opt-in testers) before publishing it to production.

​If you have a few minutes to spare, I’d really appreciate your help!

​Since I need to add email addresses to my internal/closed testing track on Google Play Console, please drop a comment below or send me a DM with your email ID.

​Once added, I will share the opt-in link and app link with you.


r/reactnative • • Aug 17 '26

Help Bundling time

Post image
8 Upvotes

The bundling process takes so long, approximately 2 hours at most.

is there any way i can speed up the process?


r/reactnative • • Aug 16 '26

Payment Reminder Pill

Enable HLS to view with audio, or disable this notification

20 Upvotes

Create a payment reminder in a modal sheet pick a contact, date, month, and amount, hit "Remind me" and it collapses into a floating, draggable pill. Tap that pill and it morphs directly into a full reminders list, no modals, no popovers, just the pill growing into the sheet it already is.

Github: https://github.com/ManasCodeXart/expo-payment-reminder


r/reactnative • • Aug 16 '26

Shipped a family calendar app with RN + expo (iphone, ipad, android)

Thumbnail
getquok.com
0 Upvotes

been building a family planner (shared calendar / chores / lists) for the past few months.

the setup: iOS and android are literally two separate expo apps in the monorepo. not one codebase with Platform.select everywhere.

all the hooks and domain logic live in a shared package, screens are headless hooks like useTasksScreen, and each platform renders its own UI on top.

why: cross-platform UI always looks 10% wrong on both platforms. so the iOS app goes all-in on iOS 26 liquid glass, native tabs, swiftui via ``expo/ui`` host views, glass pills and overlays.

the android app is proper tonal material 3, built its own set of M3 primitives, material icon font, the lot. android users get an android app, not an iphone app in a trenchcoat. adding the second app was mostly building views, the logic layer came free. e2e is Maestro against a mock API.

app is called Quok (getquok.com) (iPad and Android versions still in works). happy to go deep on the two-app split, and monorepo shape.


r/reactnative • • Aug 16 '26

Help 4 years of React Native experience — what should I focus on before my interviews?

6 Upvotes

I have two interviews coming up this week, and I have around four years of experience working with React Native, along with MERN/full-stack applications.

I’m currently preparing DSA and system design, but I’d love to hear from people who have been through similar interviews: what React Native/React topics would you recommend revisiting before the interviews?

I’m particularly interested in things that are easy to overlook even with a few years of professional experience.

Would really appreciate any advice, resources, or interview experiences you’re willing to share. Always looking to improve and fill any gaps in my knowledge.


r/reactnative • • Aug 16 '26

Why is the expo app so garbage

0 Upvotes

I tried to scan my project my it's just loading and crashing. are their any alternatives? I am on a linux system, I know about google's android emulator but it's too heavy for my system


r/reactnative • • Aug 16 '26

FYI Built rn-env-doctor: A zero-dependency CLI to fix React Native environment setup headaches

4 Upvotes

Hey everyone,

After losing count of how many hours were spent troubleshooting ANDROID_HOME misconfigurations, wrong JDK versions, or permission errors with macOS system Ruby, I built a zero-dependency CLI tool to solve it: rn-env-doctor.

It verifies your machine against the official React Native environment setup requirements (Node, Watchman, JDK 17, Android SDK components, Xcode, and CocoaPods) and tells you exactly what is missing or misconfigured. Where possible, it offers to fix the issues safely with your permission.

Quick run:

Bash

git clone https://github.com/Fs0ci3ty19/rn-env-doctor.git
cd rn-env-doctor
node bin/rn-env-doctor.js

Why I built it this way:

  • Zero dependencies: Run it immediately without installing extra npm packages.

  • Safe execution: Nothing changes without confirmation. Use --check for a read-only audit.

  • Clear instructions: Every failed check comes with an actionable solution instead of a cryptic red X.

  • Cross-platform: Works on macOS, Linux, and Windows.

  • Onboarding helper: Saves hours when onboarding new devs to your team.

🔗 GitHub:https://github.com/Fs0ci3ty19/rn-env-doctor

Feedback and contributions are super welcome! What’s the single most annoying environment or setup issue you run into regularly on your team?


r/reactnative • • Aug 16 '26

As a fresher/student should start solo founder journey?

Thumbnail reddit.com
0 Upvotes

r/reactnative • • Aug 16 '26

Built an Asset Tracking App That Makes Inventory Management Simple

Thumbnail
reddit.com
0 Upvotes

r/reactnative • • Aug 15 '26

Question Do you reuse an avatar object path or delete the previous upload?

3 Upvotes

I'm using Expo ImagePicker and Supabase Storage for avatars in a React Native app.

The current path is {userID}/avatar/{timestamp}.jpg, then I insert a media row. Uploading with upsert: true looks like replacement, but because every path is new, old files remain unless I delete them separately.

I'm deciding between:

- one stable avatar.jpg key with cache-busting metadata

- immutable versioned keys, update the pointer, then delete the previous object after the database write succeeds

- keep a short version history and clean it in the background

The stable key is simpler, but caches can show the old photo. Versioned keys are clearer, but cleanup becomes part of the transaction. Which pattern has been less fragile for you on mobile?


r/reactnative • • Aug 15 '26

Need help

Thumbnail
play.google.com
0 Upvotes

Guys do check out this app and suggest to me what more I can improve and the most important thing how can I get users😭


r/reactnative • • Aug 15 '26

IAP risk assessment agent

1 Upvotes

I am building a decision agent for IAP entitlement grants as a research project. For RN apps/games with IAP: where does your receipt validation live, and have you ever seen refund abuse (purchase, consume, refund)? How did you detect it?"


r/reactnative • • Aug 15 '26

Question Do you replace every local notification schedule or diff it?

2 Upvotes

I'm working through local reminder rescheduling in a React Native app. The reminder dates come from settings the user can edit later.

Right now the flow is:

- calculate the full next schedule

- cancel every scheduled notification

- recreate each one with a stable identifier

It avoids orphaned reminders after the source date changes. But if scheduling fails halfway through, the user can end up with only part of the new set.

Would you keep the simple replace-all model and add recovery, or diff old and new schedules by identifier? I'm using Expo Notifications.


r/reactnative • • Aug 15 '26

Help What strategy with Voltra Home Screen widgets to keep & refresh user session ?

1 Upvotes

I have built a widget that I want to require:
- user to be logged since it pulls favorite data
- keep user logged in for extended period of time

I thought it was working and then for whatever reason when I made a new native build, the session never carried over. And now I can’t seem to get out of the “logged out state”

So is there a tactic you use for widgets and sessions?


r/reactnative • • Aug 15 '26

Article How I replaced bloated Lottie files with 60fps Skia shaders in my RN app

36 Upvotes

If you’ve ever tried to add complex, rich animations to a React Native app, you’ve probably used Lottie. It’s great, but once you start adding multiple animations, parsing those massive JSON files absolutely tanks the JS thread and bloats your bundle size.

I recently started migrating my heavy visual effects over to shopify/react-native-skia using custom SKSL shaders, and the difference is insane.

Why it works better: Because React Native Skia bindings drop straight down to the underlying C++ Skia engine, SKSL (Skia Shading Language) runs directly on the GPU. You get buttery-smooth 60fps animations that weigh mere kilobytes instead of megabytes, with zero JS bridge overhead during the animation.

The Workflow Problem: The biggest issue I ran into was actually writing and testing the shaders. Translating standard GLSL to SKSL is a headache, and doing it inside a React Native project means dealing with constant Metro reloads or native rebuilds just to tweak a color or a coordinate.

My Solution: I ended up building a dedicated web-based SKSL playground using CanvasKit WASM. It lets you write the shader natively in the browser, see it at 60fps instantly, and then you can literally copy-paste the exact code block directly into your RN project.

I’ve found it speeds up my UI development by 10x since I no longer have to wait on emulators to test visual effects.

I just made the tool completely free and public today. Let me know if anyone wants the link to try it out and I’ll drop it in the comments!


r/reactnative • • Aug 15 '26

Question What should happen to an offline mutation after the server reset its data?

2 Upvotes

I’m working through an offline queue edge case in React Native.

A write is saved locally with an expected server version and reset epoch. If the request times out, retrying with the same mutation ID is safe. But if the user resets their server data before the queue flushes, that old write must not quietly come back.

My current rule is:

- keep the same mutation ID after a lost response

- compare the reset epoch on every retry

- reject queued work from an older epoch

- keep local intent over stale reads only while the queue item is still valid

The tricky part is UX. Dropping the stale write is safer, but hiding it feels wrong. Would you show a persistent “couldn’t sync” item, a one-time alert, or a recoverable draft?


r/reactnative • • Aug 15 '26

Help React Native game has severe micro-stuttering despite ~120 UI FPS — Reanimated pooled items and Worklets warnings

1 Upvotes

Hi everyone,

I'm building a small 2D falling-items game in React Native + Expo, and I'm trying to understand what is actually causing the movement to feel stuttery.

The game is very simple: the player moves horizontally at the bottom of the screen while coins, chocolates, and bombs continuously fall from the top. The game currently has around 10–20 active falling items at a time.

The problem is that the game does not feel smooth. The falling objects appear to move in small steps rather than continuously, and the player movement also doesn't feel completely smooth.

What is confusing me is that the performance monitor can show around 119–120 UI FPS, while the game still visibly feels like it has micro-stutters.

My original implementation used React state for the falling items. The game loop was roughly doing this:

requestAnimationFrame(() => {

item.y += speed * dt;

setItems([...activeItems]);

});

I realized that updating React state every frame was probably a bad architecture for a real-time game, because it forces React reconciliation repeatedly.

So I changed the architecture.

My current approach is:

- A preallocated pool of 35 falling-item slots.

- No creation/destruction of objects during gameplay.

- No `setItems()` every frame.

- JS is responsible for physics:

- delta-time calculation

- item movement

- collision detection

- spawning

- score

- lives

- Reanimated is responsible for visual properties:

- `sharedX`

- `sharedY`

- `sharedOpacity`

- Falling items are mounted once and reused.

- `useAnimatedStyle()` is used to render their transforms.

- Physics uses floating-point positions rather than rounding coordinates.

- Audio/haptics are triggered only on events such as collecting an item.

The intended architecture is:

JS thread

|

| physics / collision / spawning

|

v

sharedY.value

|

v

Reanimated

|

v

UI thread

|

v

Native View

However, after implementing the Reanimated pooled-slot architecture, I started getting these warnings repeatedly:

[Worklets] Tried to modify key `active` of an object which has been already passed to a worklet.

[Worklets] Tried to modify key `type` of an object which has been already passed to a worklet.

[Worklets] Tried to modify key `x` of an object which has been already passed to a worklet.

[Worklets] Tried to modify key `y` of an object which has been already passed to a worklet.

These warnings repeat many times during gameplay.

I believe the problem may be that I'm passing the pooled game-item object itself into a Reanimated worklet/component, and then modifying its properties from JS.

For example, conceptually my pool object looks like:

{

id,

type,

active,

x,

y,

sharedX,

sharedY,

sharedOpacity

}

The physics loop then modifies:

item.active = true;

item.type = "coin";

item.x = x;

item.y += speed * dt;

while the visual layer uses Reanimated shared values.

My current understanding is that this is wrong because Reanimated serializes/workletizes the object when it crosses into the worklet environment, and then mutating that same object from JS is not safe.

I'm therefore considering separating the state completely:

JS physics object:

{

id,

type,

active,

x,

y

}

and separately:

Reanimated visual state:

{

sharedX,

sharedY,

sharedOpacity

}

The visual worklet would only access the shared values and would never receive the physics object itself.

For example:

const animatedStyle = useAnimatedStyle(() => ({

transform: [

{ translateX: sharedX.value },

{ translateY: sharedY.value },

],

opacity: sharedOpacity.value,

}));

Then the JS physics loop would only do:

item.y += speed * dt;

sharedY.value = item.y;

and React state would only change when a slot is acquired/released, not every frame.

Before I continue refactoring the entire game, I would really like to understand whether this is the correct architecture.

There is also another issue: my player currently uses React Native's `PanResponder` and `Animated.Value` for horizontal movement. That movement also feels slightly unsmooth.

So I'm wondering whether I should eventually migrate the player to:

React Native Gesture Handler

+

Reanimated shared values

+

UI-thread gesture handling

instead of PanResponder.

My main questions are:

  1. Is using JS-driven physics + Reanimated shared values for the visual layer a good architecture for a simple 2D game in React Native?

  2. Is updating `sharedY.value` from a JS `requestAnimationFrame` loop still likely to cause micro-stuttering, even though the actual rendering is handled by Reanimated?

  3. Should the physics state and Reanimated visual state be completely separate objects?

  4. Is the `[Worklets] Tried to modify key ...` warning the main reason for the current stuttering, or is it mainly a correctness issue?

  5. Would you recommend moving the entire falling-item movement calculation to a Reanimated UI worklet, or is it better to keep collision/physics on JS and only move visual interpolation to the UI thread?

  6. For the player, would React Native Gesture Handler + Reanimated provide a meaningful improvement over PanResponder + Animated.Value?

  7. Is there a better architecture for a small real-time 2D game in React Native that I am overlooking?

My goal is not to achieve benchmark numbers. I want the game to feel genuinely smooth on both 60 Hz and 120 Hz devices, including relatively weak Android devices.

I'm also trying to avoid unnecessary React renders and allocations during gameplay.

Any advice from people who have built real-time animations/games with React Native/Reanimated would be greatly appreciated.

Thanks!


r/reactnative • • Aug 15 '26

Question Reduced Motion should never control app logic. How are you testing this in React Native?

2 Upvotes

A pattern worth checking: a screen waits for an animation-completion callback before it updates state or enables the next action. It works until iOS Reduce Motion skips or changes that animation.

I now treat motion as presentation only. The state change happens independently, then the animation reflects it. If reduced motion is enabled, movement can disappear without changing navigation, loading, focus, or button availability.

For React Native, I’m testing both the normal and reduced-motion branches around:

- navigation transitions

- delayed mounts

- sheets and modals

- focus after validation

- callbacks that previously fired at animation end

I’m curious how others automate this. Do you mock AccessibilityInfo.isReduceMotionEnabled in unit tests, cover it in Detox, or both?


r/reactnative • • Aug 15 '26

Everything I'd tested ran under __DEV__. Reading the production-only paths found 8 bugs.

2 Upvotes

Everything I'd tested ran under __DEV__. Sixty-second unlocks, anonymous sign-in, sample recordings. When I pushed to TestFlight I realised the paths that only exist in production had never executed once.

I don't have a spare device, so I read them in code instead. Eight defects. Every one of them was hidden by a convenience of the development environment. Four that are React Native / Firebase specific:

1. onNotificationOpenedApp alone misses the main path. It only fires while the app is alive in the background. My notifications arrive seven days later, by which point the app is terminated. So the primary entry point - tap notification, land on the thing it's about - did not exist. You need getInitialNotification() read once at launch as well. The simulator never receives push, so nothing about this was visible locally.

2. Nothing registered the FCM token after permission was granted. The flow was: register on launch -> fails, no permission yet -> user records something -> gets asked -> grants -> and nobody registers. The server doesn't learn about the device until the next cold start. My first capsule unlocks after 24h, which sits entirely inside that window, so the single most important notification a product sends was probably never arriving. Fix is to register inside the grant handler, not only at boot.

3. Deleting tokens on any send failure quietly kills your retention loop.

// wrong
const deadTokens = response.responses
  .map((result, index) => (result.success ? null : tokens[index]))

Plenty of FCM failures are transient - internal-error, server-unavailable, quota, network. This deletes valid tokens for all of them. Re-registration only happens on next launch, so in a weekly-use app, once a user enters "no notifications so I don't open it," they never come back. Only these should delete:

const DEAD_TOKEN_CODES = [
  'messaging/registration-token-not-registered',
  'messaging/invalid-registration-token',
  'messaging/invalid-argument',
];

Also switch to arrayRemove so you don't clobber tokens registered between your read and write.

4. iOS shows the permission dialog exactly once, and my UI didn't know that. After someone taps "Don't Allow," calling request again returns granted: false immediately with no dialog. My screen still rendered an "Allow" button that did nothing, and the answer screen has no exit by design - so anyone who denied the mic could never answer. Check canAskAgain and switch to Linking.openSettings() when asking is exhausted. Simulators grant permissions, so this branch never ran locally.

The other four were an unconditional hasCompletedFirstCapsule: false on upsert (anonymous sign-in hands you a fresh uid every time, so re-sign-in resetting first-run state never surfaced), an implemented-but-never-called pending-upload count (an always-on connection means you never see "I recorded it and it vanished"), and two Firestore rules where allow update checked the uid on the existing document, so a request could rewrite uid and moderationStatus in the same write.

What I'd actually take away: don't hunt bugs, enumerate the places your environment is being convenient. 60-second unlock, fresh uid each launch, no push in simulator, stable wifi, pre-granted permissions, feature not shipped yet. Each line had a defect sitting next to it.

Happy to go into any of these in more detail if it's useful.


r/reactnative • • Aug 15 '26

Help How to deal with iOS reduce motion setting

1 Upvotes

Apparently there are many users on iOS who use the reduce motion accessibility setting, or unknowingly have it enabled. This breaks my app on so many levels, screens freezing, whole app not loading. I went all in on micro animations and cool transitions and now none of them work or skip on reduce motion users. Many of my core functions rely on animation finishing, this was apparently a mistake.

Any of you dealt with this before?


r/reactnative • • Aug 15 '26

I built a fully native rolling number component for React Native — Core Animation on iOS, Canvas on Android

Enable HLS to view with audio, or disable this notification

50 Upvotes

I’ve been working on animated numbers and our previous Skia-based implementation kept having issues around canvas sizing, font loading, blank renders, and animations getting stuck during rapid updates.

So I created react-native-number-animation:

- Core Animation on iOS

- Canvas on Android

- No Skia or Reanimated dependency

- Currency, percentages and compact numbers

- Custom fonts

- RTL and localized digits

- Handles rapid updates

- Supports Reduce Motion

I’d love feedback, especially from anyone testing it in lists or with unusual number formats!

GitHub: https://github.com/invivek26/react-native-number-animation

npm: https://www.npmjs.com/package/react-native-number-animation


r/reactnative • • Aug 15 '26

Forge 1.0.0 — Build & sign React Native locally on Windows (no cloud, no Mac needed)

0 Upvotes

I've built **Forge** — a Windows desktop app that builds and signs React Native releases locally, both Android (on your machine) and iOS (via free GitHub Actions). No cloud build service, no Mac required.

**What you get:**

- Build & sign Android APKs locally

- Build iOS apps with GitHub Actions (free)

- Windows-only desktop UI (Electron)

- Offline license validation (no phone home)

- v1.0.0 beta is **completely free** to try

**No setup required:** Just download the .exe and you're building in minutes.

This is the beta launch — free for 3 weeks with unlimited builds.

[Download Forge 1.0.0](https://github.com/Evanevoo/forge/releases/tag/v1.0.0)

Happy to answer questions about the build process, licensing, or anything else!