Skip to content

Commit 50e8fc4

Browse files
authored
Merge pull request #17 from Nodonisko/feat/make-reanimated-optional
feat: make Reanimated optional
2 parents beb1d7d + 685acd1 commit 50e8fc4

11 files changed

Lines changed: 107 additions & 43 deletions

File tree

README.md

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@ Low overhead monitoring of important performance metrics for React Native apps l
1212
bun add react-native-performance-toolkit react-native-nitro-modules
1313
```
1414

15+
### Optional: Reanimated support
16+
17+
If you want to use UI thread components and hooks (recommended for accurate FPS display), install the optional dependencies:
18+
19+
```bash
20+
bun add react-native-reanimated react-native-worklets react-native-gesture-handler
21+
```
22+
1523
## Requirements
1624

1725
- React Native v0.76.0 or higher
18-
- Reanimated v4 or higher
26+
- (Optional) Reanimated v4 or higher - for UI thread components and hooks
1927

2028
## Usage
2129

@@ -67,11 +75,13 @@ const SomeComponent = () => {
6775

6876
### Reanimated Hooks - UI Thread
6977

78+
> **Note:** These features require `react-native-reanimated` and `react-native-worklets` to be installed. Import from `react-native-performance-toolkit/reanimated`.
79+
7080
To avoid the issue with not showing 0 FPS, it's recommended to use Reanimated based hooks or pre-made components. This will ensure the value is updated even if the JS thread is blocked.
7181

7282
```tsx
7383
import { TextInput } from 'react-native'
74-
import { useFpsJsSharedValue } from 'react-native-performance-toolkit'
84+
import { useFpsJsSharedValue } from 'react-native-performance-toolkit/reanimated'
7585
import Animated, {
7686
useAnimatedReaction,
7787
useAnimatedRef,
@@ -97,6 +107,8 @@ const SomeComponent = () => {
97107

98108
### Pre-made Reanimated components - UI Thread
99109

110+
> **Note:** These features require `react-native-reanimated`, `react-native-worklets`, and `react-native-gesture-handler` to be installed. Import from `react-native-performance-toolkit/reanimated`.
111+
100112
For better DX, the library provides pre-made Reanimated components that run solely on the UI thread. You can use either the convenience wrappers or the flexible base component:
101113

102114
```tsx
@@ -106,7 +118,7 @@ import {
106118
CpuUsageCounter,
107119
MemoryUsageCounter,
108120
UIThreadReanimatedCounter,
109-
} from 'react-native-performance-toolkit'
121+
} from 'react-native-performance-toolkit/reanimated'
110122

111123
const SomeComponent = () => {
112124
return (
@@ -157,6 +169,8 @@ console.log('Memory Usage:', getValueFromBuffer(memoryUsageBuffer))
157169

158170
### Access from worklets (advanced usage)
159171

172+
> **Note:** This requires `react-native-reanimated` and `react-native-worklets` to be installed.
173+
160174
You can also access the value from any worklet thread, but to do that you need to use [Nitro Modules unboxing function](https://nitro.margelo.com/docs/worklets). For more detailed implementation look for [source code of UI Reanimated hooks like `useFpsJsSharedValue`](https://github.com/Nodonisko/react-native-performance-toolkit/blob/main/src/hooks/uiThreadHooks.ts).
161175

162176
```tsx
@@ -187,6 +201,8 @@ const updateFps = useCallback(() => {
187201

188202
## API Reference
189203

204+
### Core API (no additional dependencies)
205+
190206
- **Simple getters**
191207
- `getJsFps(): number` - Returns current JS FPS (0-60)
192208
- `getUiFps(): number` - Returns current UI FPS (0-30/60/90/120/...)
@@ -207,12 +223,6 @@ const updateFps = useCallback(() => {
207223
- `useCpuUsage(): number` - Hook that returns current CPU usage
208224
- `useMemoryUsage(): number` - Hook that returns current memory usage
209225

210-
- **React Components (runs on UI Thread)**
211-
- `<JSFpsCounter />` - Pre-made component displaying JS FPS
212-
- `<UIFpsCounter />` - Pre-made component displaying UI FPS
213-
- `<CpuUsageCounter />` - Pre-made component displaying CPU usage
214-
- `<MemoryUsageCounter />` - Pre-made component displaying memory usage
215-
216226
- **Buffer-based API**
217227
- `getJsFpsBuffer(): ArrayBuffer` - Returns ArrayBuffer with JS FPS data
218228
- `getUiFpsBuffer(): ArrayBuffer` - Returns ArrayBuffer with UI FPS data
@@ -229,6 +239,25 @@ const updateFps = useCallback(() => {
229239
- `getDeviceMaxRefreshRate(): number`
230240
- `getDeviceCurrentRefreshRate(): number`
231241

242+
### Reanimated API (requires optional dependencies)
243+
244+
Import from `react-native-performance-toolkit/reanimated`:
245+
246+
- **React Components (runs on UI Thread)**
247+
- `<JSFpsCounter />` - Pre-made component displaying JS FPS
248+
- `<UIFpsCounter />` - Pre-made component displaying UI FPS
249+
- `<CpuUsageCounter />` - Pre-made component displaying CPU usage
250+
- `<MemoryUsageCounter />` - Pre-made component displaying memory usage
251+
- `<UIThreadReanimatedCounter label="..." type="js|ui|cpu|memory" />` - Flexible base component
252+
- `<DraggableView>` - Draggable wrapper component
253+
254+
- **Reanimated Hooks (UI Thread)**
255+
- `useFpsJsSharedValue()` - Returns SharedValue with JS FPS
256+
- `useFpsUiSharedValue()` - Returns SharedValue with UI FPS
257+
- `useFpsCpuSharedValue()` - Returns SharedValue with CPU usage
258+
- `useFpsMemorySharedValue()` - Returns SharedValue with memory usage
259+
- `useCounterSharedValue(type)` - Generic hook for any counter type
260+
232261
## Architecture
233262

234263
### Low overhead tracking

bun.lock

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
UIFpsCounter,
1515
CpuUsageCounter,
1616
MemoryUsageCounter,
17-
} from 'react-native-performance-toolkit';
17+
} from 'react-native-performance-toolkit/reanimated';
1818

1919
function formatValue(value: number): string {
2020
return Number.isFinite(value) ? value.toFixed(0) : '0';

example/babel.config.js

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
1-
const path = require('path');
2-
const pak = require('../package.json');
3-
41
module.exports = api => {
52
api.cache(true);
63
return {
74
presets: ['module:@react-native/babel-preset'],
8-
plugins: [
9-
[
10-
'module-resolver',
11-
{
12-
extensions: ['.js', '.ts', '.json', '.jsx', '.tsx'],
13-
alias: {
14-
[pak.name]: path.join(__dirname, '../', pak.source),
15-
},
16-
},
17-
],
18-
'react-native-worklets/plugin',
19-
],
5+
plugins: ['react-native-worklets/plugin'],
206
};
217
};

example/metro.config.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
22
const path = require('path');
3+
const pak = require('../package.json');
34
const root = path.resolve(__dirname, '..');
45

56
/**
@@ -10,6 +11,25 @@ const root = path.resolve(__dirname, '..');
1011
*/
1112
const config = {
1213
watchFolders: [root],
14+
resolver: {
15+
resolveRequest: (context, moduleName, platform) => {
16+
// Handle subpath import
17+
if (moduleName === `${pak.name}/reanimated`) {
18+
return {
19+
filePath: path.resolve(__dirname, '../src/reanimated.tsx'),
20+
type: 'sourceFile',
21+
};
22+
}
23+
// Handle main package import
24+
if (moduleName === pak.name) {
25+
return {
26+
filePath: path.resolve(__dirname, '../src/index.tsx'),
27+
type: 'sourceFile',
28+
};
29+
}
30+
return context.resolveRequest(context, moduleName, platform);
31+
},
32+
},
1333
};
1434

1535
module.exports = mergeConfig(getDefaultConfig(__dirname), config);

example/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"strict": true,
77
"baseUrl": ".",
88
"paths": {
9-
"react-native-performance-toolkit": ["../src"]
9+
"react-native-performance-toolkit": ["../src"],
10+
"react-native-performance-toolkit/reanimated": ["../src/reanimated"]
1011
}
1112
}
1213
}

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"ios/**/*.swift",
3939
"app.plugin.js",
4040
"*.podspec",
41+
"reanimated.js",
42+
"reanimated.d.ts",
4143
"README.md",
4244
"!example",
4345
"!media"
@@ -79,6 +81,17 @@
7981
"react-native-worklets": "*",
8082
"react-native-gesture-handler": "*"
8183
},
84+
"peerDependenciesMeta": {
85+
"react-native-reanimated": {
86+
"optional": true
87+
},
88+
"react-native-worklets": {
89+
"optional": true
90+
},
91+
"react-native-gesture-handler": {
92+
"optional": true
93+
}
94+
},
8295
"eslintConfig": {
8396
"root": true,
8497
"extends": [

reanimated.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './lib/typescript/src/reanimated'

reanimated.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./lib/commonjs/reanimated.js')

src/index.tsx

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import './specs/TurboPerformanceToolkit'
22

3-
import React from 'react'
4-
import { UIThreadReanimatedCounter } from './components/UIThreadReanimatedCounter'
53
import { PerformanceToolkit } from './hybrids'
64

75
export {
@@ -11,21 +9,6 @@ export {
119
PerformanceToolkit,
1210
} from './hybrids'
1311

14-
export const JSFpsCounter = () => {
15-
return <UIThreadReanimatedCounter label="JS FPS" type="js" />
16-
}
17-
18-
export const UIFpsCounter = () => {
19-
return <UIThreadReanimatedCounter label="UI FPS" type="ui" />
20-
}
21-
22-
export const CpuUsageCounter = () => {
23-
return <UIThreadReanimatedCounter label="CPU" type="cpu" />
24-
}
25-
export const MemoryUsageCounter = () => {
26-
return <UIThreadReanimatedCounter label="RAM" type="memory" />
27-
}
28-
2912
export const getDeviceMaxRefreshRate = () =>
3013
PerformanceToolkit.getDeviceMaxRefreshRate()
3114

0 commit comments

Comments
 (0)