Skip to content

Commit 3c383f2

Browse files
committed
fix: use non-deprecated APIs + enable Nitro auto-box
Upgrade react-native-worklets to 0.7.4 enabling automatic HybridObject serialization across worklet boundaries. Switch to scheduleOnUI and async ViewModel APIs. Add react-query for async data loading in exerciser.
1 parent 0d051d7 commit 3c383f2

5 files changed

Lines changed: 108 additions & 63 deletions

File tree

example/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
"@react-native-picker/picker": "^2.11.4",
1919
"@react-navigation/native": "^7.1.9",
2020
"@react-navigation/stack": "^7.3.2",
21+
"@tanstack/react-query": "^5.100.10",
2122
"react": "19.0.0",
2223
"react-native": "0.79.2",
2324
"react-native-gesture-handler": "2.29.1",
2425
"react-native-nitro-modules": "0.35.0",
25-
"react-native-reanimated": "4.1.5",
26+
"react-native-reanimated": "4.2.0",
2627
"react-native-safe-area-context": "^5.4.0",
2728
"react-native-screens": "~4.18.0",
28-
"react-native-worklets": "0.6.1"
29+
"react-native-worklets": "0.7.4"
2930
},
3031
"devDependencies": {
3132
"@babel/core": "^7.25.2",

example/src/App.tsx

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { NavigationContainer, useNavigation } from '@react-navigation/native';
1212
import { createStackNavigator } from '@react-navigation/stack';
1313
import AsyncStorage from '@react-native-async-storage/async-storage';
14+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
1415
import { PagesList, type PageItem } from './PagesList';
1516
import { HomeMenu } from './shared/HomeMenu';
1617

@@ -95,38 +96,42 @@ function HomeScreen({ navigation }: { navigation: any }) {
9596
);
9697
}
9798

99+
const queryClient = new QueryClient();
100+
98101
export default function App() {
99102
return (
100-
<NavigationContainer>
101-
<Stack.Navigator
102-
screenOptions={{
103-
headerStyle: {
104-
backgroundColor: '#323232',
105-
},
106-
headerTintColor: '#fff',
107-
headerTitleStyle: {
108-
fontWeight: 'bold',
109-
},
110-
}}
111-
>
112-
<Stack.Screen
113-
name="Home"
114-
component={HomeScreen}
115-
options={{
116-
title: 'Rive Examples',
117-
headerRight: HeaderMenuButton,
103+
<QueryClientProvider client={queryClient}>
104+
<NavigationContainer>
105+
<Stack.Navigator
106+
screenOptions={{
107+
headerStyle: {
108+
backgroundColor: '#323232',
109+
},
110+
headerTintColor: '#fff',
111+
headerTitleStyle: {
112+
fontWeight: 'bold',
113+
},
118114
}}
119-
/>
120-
{PagesList.map(({ id, component, name }) => (
115+
>
121116
<Stack.Screen
122-
key={id}
123-
name={id}
124-
component={component}
125-
options={{ title: name }}
117+
name="Home"
118+
component={HomeScreen}
119+
options={{
120+
title: 'Rive Examples',
121+
headerRight: HeaderMenuButton,
122+
}}
126123
/>
127-
))}
128-
</Stack.Navigator>
129-
</NavigationContainer>
124+
{PagesList.map(({ id, component, name }) => (
125+
<Stack.Screen
126+
key={id}
127+
name={id}
128+
component={component}
129+
options={{ title: name }}
130+
/>
131+
))}
132+
</Stack.Navigator>
133+
</NavigationContainer>
134+
</QueryClientProvider>
130135
);
131136
}
132137

example/src/exercisers/RiveToReactNativeExample.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import {
77
Switch,
88
} from 'react-native';
99
import { useEffect, useMemo, useState } from 'react';
10+
import { useQuery } from '@tanstack/react-query';
1011
import Animated, {
11-
runOnUI,
1212
useSharedValue,
1313
useAnimatedStyle,
1414
type SharedValue,
1515
} from 'react-native-reanimated';
16-
import { NitroModules } from 'react-native-nitro-modules';
16+
import { scheduleOnUI } from 'react-native-worklets';
1717
import {
1818
Fit,
1919
RiveView,
@@ -29,7 +29,7 @@ declare global {
2929
var __callMicrotasks: () => void;
3030
}
3131

32-
installWorkletDispatcher(runOnUI);
32+
installWorkletDispatcher(scheduleOnUI);
3333

3434
function useRiveNumberListener(
3535
property: ViewModelNumberProperty | undefined,
@@ -40,18 +40,16 @@ function useRiveNumberListener(
4040
if (!property) return;
4141

4242
if (useUIThread) {
43-
const boxedProperty = NitroModules.box(property);
4443
const sv = sharedValue;
4544

46-
runOnUI(() => {
45+
scheduleOnUI(() => {
4746
'worklet';
48-
const prop = boxedProperty.unbox();
49-
prop.addListener((value: number) => {
47+
property.addListener((value: number) => {
5048
'worklet';
5149
sv.value = value;
5250
global.__callMicrotasks();
5351
});
54-
})();
52+
});
5553

5654
return () => {
5755
property.removeListeners();
@@ -78,32 +76,40 @@ export default function RiveToReactNativeExample() {
7876
) : riveFile ? (
7977
<WithViewModelSetup file={riveFile} />
8078
) : (
81-
<Text style={styles.errorText}>{error?.message || 'Unexpected error'}</Text>
79+
<Text style={styles.errorText}>
80+
{error?.message || 'Unexpected error'}
81+
</Text>
8282
)}
8383
</View>
8484
);
8585
}
8686

8787
function WithViewModelSetup({ file }: { file: RiveFile }) {
88-
const viewModel = useMemo(() => file.defaultArtboardViewModel(), [file]);
89-
const instance = useMemo(
90-
() => viewModel?.createDefaultInstance(),
91-
[viewModel]
92-
);
9388
const [useUIThread, setUseUIThread] = useState(true);
9489

95-
if (!instance || !viewModel) {
90+
const { data: instance, error } = useQuery({
91+
queryKey: ['bouncing-ball-instance', file],
92+
queryFn: async () => {
93+
const vm = await file.defaultArtboardViewModelAsync();
94+
if (!vm) throw new Error('No view model found.');
95+
const inst = await vm.createDefaultInstanceAsync();
96+
if (!inst) throw new Error('Failed to create view model instance');
97+
return inst;
98+
},
99+
});
100+
101+
if (error) {
96102
return (
97103
<View style={styles.errorContainer}>
98-
<Text style={styles.errorText}>
99-
{!viewModel
100-
? 'No view model found.'
101-
: 'Failed to create view model instance'}
102-
</Text>
104+
<Text style={styles.errorText}>{error.message}</Text>
103105
</View>
104106
);
105107
}
106108

109+
if (!instance) {
110+
return <ActivityIndicator size="large" color="#0000ff" />;
111+
}
112+
107113
return (
108114
<BouncingBallTracker
109115
instance={instance}

src/core/WorkletBridge.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,24 @@ let isInstalled = false;
1010
*
1111
* Call this once at app startup. It will schedule the installation on the UI thread.
1212
*
13-
* @param runOnUI - The runOnUI function from react-native-reanimated
13+
* Requires react-native-worklets >= 0.7.1 for automatic HybridObject serialization.
14+
*
15+
* @param scheduleOnUI - The scheduleOnUI function from react-native-worklets
1416
*
1517
* @example
1618
* ```tsx
1719
* import { installWorkletDispatcher } from '@rive-app/react-native';
18-
* import { runOnUI } from 'react-native-reanimated';
20+
* import { scheduleOnUI } from 'react-native-worklets';
1921
*
2022
* // Call once at app startup
21-
* installWorkletDispatcher(runOnUI);
23+
* installWorkletDispatcher(scheduleOnUI);
2224
* ```
2325
*/
2426
export function installWorkletDispatcher(
25-
runOnUI: <Args extends unknown[], ReturnValue>(
26-
worklet: (...args: Args) => ReturnValue
27-
) => (...args: Args) => void
27+
scheduleOnUI: <Args extends unknown[], ReturnValue>(
28+
worklet: (...args: Args) => ReturnValue,
29+
...args: Args
30+
) => void
2831
): void {
2932
if (isInstalled) {
3033
return;
@@ -34,11 +37,8 @@ export function installWorkletDispatcher(
3437
const bridge =
3538
NitroModules.createHybridObject<RiveWorkletBridge>('RiveWorkletBridge');
3639

37-
const boxedBridge = NitroModules.box(bridge);
38-
39-
runOnUI(() => {
40+
scheduleOnUI(() => {
4041
'worklet';
41-
const b = boxedBridge.unbox();
42-
b.install();
43-
})();
42+
bridge.install();
43+
});
4444
}

yarn.lock

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5563,6 +5563,24 @@ __metadata:
55635563
languageName: node
55645564
linkType: hard
55655565

5566+
"@tanstack/query-core@npm:5.100.10":
5567+
version: 5.100.10
5568+
resolution: "@tanstack/query-core@npm:5.100.10"
5569+
checksum: d19351b858bd758ad8a860e9333c9b78c1ec4a564b867f592046a60cf8421580d8aefcb3dfc3c67d59c5f8cf3dee9a3074ac07204e37ec54012fd912246d0dbd
5570+
languageName: node
5571+
linkType: hard
5572+
5573+
"@tanstack/react-query@npm:^5.100.10":
5574+
version: 5.100.10
5575+
resolution: "@tanstack/react-query@npm:5.100.10"
5576+
dependencies:
5577+
"@tanstack/query-core": 5.100.10
5578+
peerDependencies:
5579+
react: ^18 || ^19
5580+
checksum: 90ceb6cafa573a081bcaf03e727ab99e68c71464dc65cede626c3c10c848d136f33ffb6523a04c477448d46d320b202b5d93fbb6f1cb4bef27fd3af3ff43cbee
5581+
languageName: node
5582+
linkType: hard
5583+
55665584
"@testing-library/react-hooks@npm:^8.0.1":
55675585
version: 8.0.1
55685586
resolution: "@testing-library/react-hooks@npm:8.0.1"
@@ -16321,6 +16339,20 @@ __metadata:
1632116339
languageName: node
1632216340
linkType: hard
1632316341

16342+
"react-native-reanimated@npm:4.2.0":
16343+
version: 4.2.0
16344+
resolution: "react-native-reanimated@npm:4.2.0"
16345+
dependencies:
16346+
react-native-is-edge-to-edge: 1.2.1
16347+
semver: 7.7.3
16348+
peerDependencies:
16349+
react: "*"
16350+
react-native: "*"
16351+
react-native-worklets: ">=0.7.0"
16352+
checksum: a8a4c321513cdca93a66b90c284c86eb56b05ac7d8989cd36b3e090055b59b9613870891868432835a13d1ddcaad3b1763bb9c7ed267616d90e138625d15ef23
16353+
languageName: node
16354+
linkType: hard
16355+
1632416356
"react-native-reanimated@npm:4.2.1":
1632516357
version: 4.2.1
1632616358
resolution: "react-native-reanimated@npm:4.2.1"
@@ -16354,6 +16386,7 @@ __metadata:
1635416386
"@react-native/typescript-config": 0.79.2
1635516387
"@react-navigation/native": ^7.1.9
1635616388
"@react-navigation/stack": ^7.3.2
16389+
"@tanstack/react-query": ^5.100.10
1635716390
"@types/deep-equal": ^1.0.4
1635816391
"@types/react": ^19.0.0
1635916392
babel-plugin-react-compiler: ^1.0.0
@@ -16364,10 +16397,10 @@ __metadata:
1636416397
react-native-gesture-handler: 2.29.1
1636516398
react-native-harness: 1.0.0
1636616399
react-native-nitro-modules: 0.35.0
16367-
react-native-reanimated: 4.1.5
16400+
react-native-reanimated: 4.2.0
1636816401
react-native-safe-area-context: ^5.4.0
1636916402
react-native-screens: ~4.18.0
16370-
react-native-worklets: 0.6.1
16403+
react-native-worklets: 0.7.4
1637116404
languageName: unknown
1637216405
linkType: soft
1637316406

0 commit comments

Comments
 (0)