Skip to content

Commit fedbd6d

Browse files
avishayilabarcybrclaude
authored
fix: address release blockers and polish README (#305)
- iOS: implement getReason (was declared in the TS API and implemented on Android/Windows but missing on iOS, so getReason() threw on iOS) - JS: route restart/Restart/getReason through the TurboModule spec (TurboModuleRegistry) with a NativeModules fallback and a clear linking error instead of a "spread undefined" crash; restart() now dispatches to the non-deprecated native restart - .release-it.json: use ${version} instead of hard-coded 0.0.27 - android/gradle.properties: align SDK versions to 36/24/36 (match build.gradle) - .husky/pre-commit: run lint + typescript + test (matches CONTRIBUTING) - README: restructured with fixed badges, features, platform/architecture support table, API table, and collapsible legacy install steps - tests: cover restart(null)/reason, deprecated Restart alias, and getReason Co-authored-by: abar <avishay.bar@cyberark.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8b1b7f9 commit fedbd6d

7 files changed

Lines changed: 196 additions & 171 deletions

File tree

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env sh
22
. "$(dirname -- "$0")/_/husky.sh"
33

4-
npm test
4+
npm run lint && npm run typescript && npm test

.release-it.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"git": {
3-
"commitMessage": "chore: release 0.0.27",
4-
"tagName": "v0.0.27",
3+
"commitMessage": "chore: release ${version}",
4+
"tagName": "v${version}",
55
"requireBranch": "master"
66
},
77
"npm": {

README.md

Lines changed: 110 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,191 +1,151 @@
1-
# React Native Restart
1+
<div align="center">
22

3-
[![npm version](https://img.shields.io/npm/v/react-native-restart.svg?style=flat-square)](https://www.npmjs.com/package/react-native-restart)
4-
[![npm downloads](https://img.shields.io/npm/dm/react-native-restart.svg?style=flat-square)](https://www.npmjs.com/package/react-native-restart)
5-
[![Build status](https://github.com/avishayil/react-native-restart/actions/workflows/main.yml/badge.svg)](https://github.com/avishayil/react-native-restart/actions/workflows/main.yml)
3+
# 🔄 React Native Restart
64

7-
Sometimes you want to reload your app bundle during app runtime. This package will allow you to do it.
5+
**Programmatically reload the JavaScript bundle / restart your React Native app at runtime.**
86

9-
iOS GIF | Android GIF
10-
:-------------------------:|:-------------------------:
11-
<img src="./images/ios.gif" title="iOS GIF" width="250"> | <img src="./images/android.gif" title="Android GIF" width="250">
7+
[![npm version](https://img.shields.io/npm/v/react-native-restart.svg?style=flat-square)](https://www.npmjs.com/package/react-native-restart)
8+
[![npm downloads](https://img.shields.io/npm/dm/react-native-restart.svg?style=flat-square)](https://www.npmjs.com/package/react-native-restart)
9+
[![Build status](https://github.com/avishayil/react-native-restart/actions/workflows/ci.yml/badge.svg)](https://github.com/avishayil/react-native-restart/actions/workflows/ci.yml)
10+
[![License: MIT](https://img.shields.io/npm/l/react-native-restart.svg?style=flat-square)](./LICENSE)
11+
12+
![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Windows-blue?style=flat-square)
13+
![New Architecture](https://img.shields.io/badge/New%20Architecture-supported-success?style=flat-square)
14+
![TypeScript](https://img.shields.io/badge/TypeScript-typed-3178c6?style=flat-square)
15+
16+
</div>
17+
18+
<table>
19+
<tr>
20+
<th align="center">iOS</th>
21+
<th align="center">Android</th>
22+
</tr>
23+
<tr>
24+
<td align="center"><img src="./images/ios.gif" title="iOS demo" width="250"></td>
25+
<td align="center"><img src="./images/android.gif" title="Android demo" width="250"></td>
26+
</tr>
27+
</table>
28+
29+
Common use cases: applying an RTL/LTR locale change, recovering from a fatal JS state,
30+
resetting the app after login/logout, or clearing in-memory state without asking the user
31+
to kill and reopen the app.
32+
33+
## Features
34+
35+
- ✅ One call to restart — `RNRestart.restart()`
36+
-**iOS, Android & Windows** support
37+
-**New Architecture (TurboModule/Fabric) and legacy architecture** both supported
38+
- ✅ Optional restart **reason** you can read back after the restart (`getReason()`)
39+
- ✅ Fully typed (TypeScript) with a codegen TurboModule spec
40+
41+
## Platform & architecture support
42+
43+
| Platform | Restart mechanism | Old Arch | New Arch |
44+
| --- | --- | :---: | :---: |
45+
| iOS | Reloads the JS bundle (`RCTTriggerReloadCommandListeners`) |||
46+
| Android | Full process restart (`ProcessPhoenix`) |||
47+
| Windows | Reloads the instance (`ReactNativeHost.ReloadInstance`) |||
48+
49+
> On **Android** the whole process is restarted, so native state **and** the JS runtime are
50+
> reinitialized. On **iOS/Windows** the JS bundle is reloaded in-process. The optional restart
51+
> reason survives the restart and is returned by `getReason()` on the next launch.
1252
1353
## Installation
1454

15-
- Using `react-native < 0.62`? install `react-native-restart@0.0.17`
16-
- Using `0.71 > react-native >= 0.62`? install `react-native-restart@0.0.24`
17-
- Using `0.72 - 0.84`? install `react-native-restart@0.0.28`
18-
- Using `react-native >= 0.85`? install `react-native-restart@0.0.28` and above
19-
20-
## Requirements
21-
22-
For React Native 0.85.3+:
23-
- React Native 0.85.3+
24-
- React 19.2.3+
25-
- Node.js 20.19.4+ (or 22.13.0+, 24.3.0+, 25.0.0+)
26-
- iOS 15.1+
27-
- Xcode 16.1+
28-
- Android API 24+ (Android 7.0+)
29-
- Android SDK 36
30-
- Java 17 (for Android development)
31-
- Gradle 9.3.1
32-
- Windows: `react-native-windows` 0.84.0+ (optional peer dependency, New Architecture)
33-
34-
### With `yarn`
35-
36-
```bash
37-
$ yarn add react-native-restart
38-
```
39-
40-
### With `npm`
4155
```bash
42-
$ npm install --save react-native-restart
56+
npm install react-native-restart
57+
# or
58+
yarn add react-native-restart
4359
```
4460

45-
## Auto-Linking Setup (react-native >= 0.60)
46-
47-
### iOS
61+
Match the package version to your React Native version:
4862

49-
```bash
50-
$ cd ios
51-
$ pod install
52-
```
63+
| React Native | Install |
64+
| --- | --- |
65+
| `>= 0.85` | `react-native-restart@latest` |
66+
| `0.72 – 0.84` | `react-native-restart@0.0.28` |
67+
| `0.62 – 0.71` | `react-native-restart@0.0.24` |
68+
| `< 0.62` | `react-native-restart@0.0.17` |
5369

54-
### Android
70+
**Requirements (RN 0.85+):** React 19.2+, Node 20.19+ / 22.13+ / 24.3+, iOS 15.1+ &
71+
Xcode 16.1+, Android API 24+ (SDK 36, Java 17, Gradle 9.3+), and — for Windows —
72+
`react-native-windows` 0.84+ (optional peer dependency).
5573

56-
No further steps should be taken
57-
58-
### Windows
59-
60-
Requires `react-native-windows` 0.84.0 or higher. The module is picked up by autolinking:
61-
62-
```bash
63-
$ npx react-native autolink-windows
64-
```
74+
### Linking
6575

66-
This also runs automatically as part of `npx react-native run-windows`.
76+
Autolinking (React Native ≥ 0.60) handles everything:
6777

68-
## Automatic Installation (Without Auto-Linking)
78+
- **iOS:** `cd ios && pod install`
79+
- **Android:** no extra steps
80+
- **Windows:** `npx react-native autolink-windows` (runs automatically as part of `run-windows`)
6981

70-
`react-native link react-native-restart` or `npm install -g rnpm && rnpm link react-native-restart`
82+
<details>
83+
<summary>Manual installation (legacy React Native, without autolinking)</summary>
7184

72-
## Manual Android Installation
85+
#### Android `android/settings.gradle`
7386

74-
In `android/settings.gradle`
7587
```gradle
76-
...
77-
7888
include ':react-native-restart'
7989
project(':react-native-restart').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-restart/android')
8090
```
8191

82-
In `android/app/build.gradle`
92+
`android/app/build.gradle`:
8393

8494
```gradle
85-
...
86-
8795
dependencies {
88-
...
89-
9096
implementation project(':react-native-restart')
9197
}
9298
```
9399

94-
Register module (in `MainApplication.java`)
100+
Register the package in `MainApplication`:
95101

96102
```java
97-
import com.reactnativerestart.RestartPackage; // <--- Import
98-
99-
public class MainApplication extends Application implements ReactApplication {
100-
101-
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
102-
......
103-
104-
/**
105-
* A list of packages used by the app. If the app uses additional views
106-
* or modules besides the default ones, add more packages here.
107-
*/
108-
@Override
109-
protected List<ReactPackage> getPackages() {
110-
...
111-
return Arrays.<ReactPackage>asList(
112-
new MainReactPackage(),
113-
new RestartPackage() // Add this line
114-
);
115-
}
116-
};
117-
......
118-
};
103+
import com.reactnativerestart.RestartPackage; // <--- import
119104

105+
// ...in getPackages():
106+
new RestartPackage()
120107
```
121108

122-
## Manual iOS Installation
123-
124-
### Importing The Library
125-
126-
* Drag the file `Restart.xcodeproj` from `/node_modules/react-native-restart/ios` into the `Libraries` group in the Project navigator. Ensure that `Copy items if needed` is UNCHECKED!
127-
128-
![Add Files To...](http://i.imgur.com/puxHiIg.png)
129-
130-
![Library Imported Successfully](http://i.imgur.com/toZUWg5.png)
131-
132-
* Ensure that `libRestart.a` is linked through `Link Binary With Libraries` on `Build Phases`:
109+
#### iOS (manual / CocoaPods)
133110

134-
![Library Linked](http://i.imgur.com/Sm1birt.png)
135-
136-
* Ensure that `Header Search Paths` on `Build Settings` has the path `$(SRCROOT)/../node_modules/react-native-restart` set to `recursive`:
137-
138-
* You're All Set!
139-
140-
## CocoaPod iOS Installation
141-
142-
In your `ios/Podfile` make sure to use `react-native-restart` from the local
143-
`node_modules/`. With that, only your project Pod needs to be linked and
144-
no extra configuration is required:
111+
Add to your `ios/Podfile`:
145112

146113
```ruby
147-
target 'MyReactApp' do
148-
# Make sure you're also using React-Native from ../node_modules
149-
pod 'React', :path => '../node_modules/react-native', :subspecs => [
150-
'Core',
151-
'RCTActionSheet',
152-
# ... whatever else you use
153-
]
154-
# React-Native dependencies such as yoga:
155-
pod 'yoga', path: '../node_modules/react-native/ReactCommon/yoga'
156-
157-
# The following line uses react-native-restart, linking with
158-
# the library and setting the Header Search Paths for you
159-
pod 'react-native-restart', :path => '../node_modules/react-native-restart'
160-
end
114+
pod 'react-native-restart', :path => '../node_modules/react-native-restart'
161115
```
162116

163-
Remember to run `cd ios && pod install` to update files used by Xcode.
117+
Then `cd ios && pod install`. (For very old projects you can instead drag
118+
`Restart.xcodeproj` from `node_modules/react-native-restart/ios` into your Xcode
119+
`Libraries` group and link `libRestart.a`.)
120+
121+
</details>
164122

165123
## Usage
166124

167125
```javascript
168-
import RNRestart from 'react-native-restart'; // Import package from node modules
126+
import RNRestart from 'react-native-restart';
169127

170-
// Restart the application
171-
RNRestart.Restart(); // Deprecated
128+
// Restart the app (reloads the JS bundle; full process restart on Android)
172129
RNRestart.restart();
173130

174-
// Optionally make a reason available after the restart
131+
// Optionally attach a reason, then read it back after the restart
175132
RNRestart.restart('language-change');
176-
const reason = await RNRestart.getReason();
133+
const reason = await RNRestart.getReason(); // => 'language-change'
177134
```
178135

179-
On Android, `restart()` restarts the application process so both native state
180-
and the JavaScript runtime are reinitialized. On iOS, it reloads the React
181-
Native bundle. The optional restart reason survives the Android process restart
182-
and is returned by `getReason()` after the application starts again.
136+
### API
137+
138+
| Method | Description |
139+
| --- | --- |
140+
| `restart(reason?: string): void` | Restart the app. Preferred entry point. |
141+
| `Restart(reason?: string): void` | **Deprecated** alias of `restart` (kept for backward compatibility). |
142+
| `getReason(): Promise<string \| null>` | The reason passed to the last restart, or `null`. Survives the restart. |
183143

184144
### White screen during restart
185145

186-
Because `restart()` tears down the view hierarchy and remounts the app, there is a
187-
brief gap before the new instance renders — on iOS this can look like a white flash.
188-
To avoid the flash, set your root view's background color natively in `AppDelegate`:
146+
Because `restart()` tears down the view hierarchy and remounts the app, there is a brief gap
147+
before the new instance renders — on iOS this can look like a white flash. To avoid it, set
148+
your root view's background color natively in `AppDelegate`:
189149

190150
```objc
191151
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
@@ -197,20 +157,27 @@ To avoid the flash, set your root view's background color natively in `AppDelega
197157
}
198158
```
199159

200-
Showing a full splash screen for the duration of the restart requires additional
201-
app-side native code (a native launch screen shown on app launch). See
160+
A full splash screen for the duration of the restart needs additional app-side native code
161+
(a native launch screen shown on app launch). See
202162
[#238](https://github.com/avishayil/react-native-restart/issues/238).
203163

204164
## Architecture
205165

206-
This library is a thin JS bridge (`src/index.tsx`) over three native implementations of an `RNRestart` module — iOS (`ios/`), Android (`android/`), and Windows (`windows/`). Any public-API change must be made across the JS layer and all native platforms together.
207-
208-
For a full overview of the structure, commands, build/publish flow, and conventions — aimed at both contributors and AI agents — see [CLAUDE.md](CLAUDE.md).
166+
A thin JS bridge (`src/index.tsx` + the TurboModule spec `src/NativeRNRestart.ts`) over native
167+
`RNRestart` modules on iOS (`ios/`), Android (`android/`), and Windows (`windows/`). Any
168+
public-API change must be made across the JS layer and every native platform together. For a
169+
full overview of structure, commands, build/publish flow, and conventions — for contributors
170+
and AI agents — see [CLAUDE.md](CLAUDE.md).
209171

210172
## Contributing
211173

212-
Contributions are welcome. Please see [CONTRIBUTING.md](CONTRIBUTING.md) if you like to contribute to this library.
174+
Contributions are welcome see [CONTRIBUTING.md](CONTRIBUTING.md).
213175

214176
## Credits
215177

216-
Thanks to Microsoft CodePush library. I simply extracted the code from their library's logic to reload the React Native Bundle.
178+
Thanks to the Microsoft CodePush library; the original bundle-reload logic was extracted from
179+
there.
180+
181+
## License
182+
183+
[MIT](./LICENSE)

android/gradle.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
compileSdkVersion=33
2-
minSdkVersion=21
3-
targetSdkVersion=33
1+
compileSdkVersion=36
2+
minSdkVersion=24
3+
targetSdkVersion=36

ios/Restart.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ - (void)loadBundle
3434
return;
3535
}
3636

37+
RCT_EXPORT_METHOD(getReason: (RCTPromiseResolveBlock)resolve
38+
reject: (RCTPromiseRejectBlock)reject) {
39+
resolve(restartReason);
40+
}
41+
3742
@end

0 commit comments

Comments
 (0)