$ show avishayil/react-native-restart
react-native-restart is a small React Native native module that programmatically reloads the running JS bundle at runtime — a full process restart on Android, a bundle reload in-process on iOS and Windows. The architecture is a deliberately thin TypeScript bridge (src/index.tsx) over three native implementations, all registered under the module name RNRestart. The JS layer resolves the native module through TurboModuleRegistry on the New Architecture with a NativeModules fallback for the legacy bridge, and throws a descriptive linking error when the module was never linked. A TurboModule spec (src/NativeRNRestart.ts) drives RN codegen on Android and Windows. The public API is just three calls: restart(reason?), the deprecated Restart(reason?) alias, and getReason() which returns a reason that survives the restart.
The LLM identified 3 files worth highlighting for reuse:
Clean JS bridge that resolves the native RNRestart module via TurboModuleRegistry on the New Architecture and falls back to NativeModules on the legacy bridge, then throws a descriptive linking error instead of an opaque runtime crash. It imports only from react-native and one local spec, so the pattern can be lifted into any React Native library that must support both architectures.
A well-crafted test seam: a category exposes the private loadBundle method, a TestableRestart subclass records the reload attempt instead of calling RCTTriggerReloadCommandListeners (which would reload and crash the live test host), and the real reload behavior is covered separately by a Maestro E2E flow. Demonstrates how to safely unit-test side-effecting native code by isolating the destructive call and verifying it end-to-end at a higher layer.
Android native module that performs a full process restart via ProcessPhoenix. It persists an optional restart reason to SharedPreferences using synchronous commit() — a deliberate choice because the process is killed immediately and async apply() may not flush — then consumes the key on next launch into a static field so the reason survives process death and is exposed to JS via getReason(). A reusable reference for any 'persist state across a destructive restart' scenario.