Migrating from rive-react-native to @rive-app/react-native
The new Rive React Native runtime (@rive-app/react-native) is a complete rewrite built with Nitro Modules for improved performance and better React Native integration.
All your Rive graphics will still look and function the same as they did
before.
What’s New
RiveFile Ownership: You now own the RiveFile object via the useRiveFile hook, enabling file caching, multiple instances from one file, and better resource management.
// Old: file managed internally
<Rive url="https://cdn.rive.app/animations/vehicles.riv" />
// New: you own the RiveFile
const { riveFile } = useRiveFile(require("./vehicles.riv"));
<RiveView file={riveFile} />
Enhanced Data Binding: Direct access to ViewModel and ViewModelInstance objects, enabling initialization hooks, multiple instances, and support for all property types (lists, images, artboards).
// Old: hooks take riveRef, return tuples
const [setRiveRef, riveRef] = useRive();
const [health, setHealth] = useRiveNumber(riveRef, "health");
// New: hooks take viewModelInstance, return objects
const viewModelInstance = useViewModelInstance(riveFile);
const { value: health, setValue: setHealth } = useRiveNumber(
"health",
viewModelInstance
);
Improved Error Handling:
Error handling is improved. See the error handling documentation for more information.
Requirements
- React Native: 0.78+ (0.79+ recommended)
- Expo SDK: 53+ (for Expo users)
- iOS: 15.1+
- Android: SDK 24+
- Xcode: 16.4+
- JDK: 17+
- Nitro Modules: 0.25.2+
Migration Steps
1. Installation
npm uninstall rive-react-native
npm install @rive-app/react-native react-native-nitro-modules
react-native-nitro-modules is required as this library relies on Nitro
Modules.
2. Update Imports
// Old
import Rive from "rive-react-native";
// New
import { RiveView } from "@rive-app/react-native";
3. Loading Rive Files
New Runtime
Legacy Runtime
const { riveFile, isLoading, error } = useRiveFile(require('./animation.riv'));
// Also supports: URL string, resource name, or ArrayBuffer
return <RiveView file={riveFile} style={{ width: 400, height: 400 }} />;
<Rive source={require('./animation.riv')} />
// Also supports: url or resourceName props
See loading Rive files for more information.
4. Component Migration
New Runtime
Legacy Runtime
<RiveView
file={riveFile}
artboardName="MainArtboard"
stateMachineName="State Machine 1"
fit={Fit.Contain}
autoPlay={true}
style={{ width: 400, height: 400 }}
/>
<Rive
url="https://cdn.rive.app/animations/vehicles.riv"
artboardName="MainArtboard"
stateMachineName="State Machine 1"
fit={Fit.Contain}
autoplay={true}
style={{ width: 400, height: 400 }}
/>
See React Native runtime and props documentation for more information.
5. View Reference Migration
New Runtime
Legacy Runtime
const { riveViewRef, setHybridRef } = useRive();
riveViewRef?.play();
riveViewRef?.pause();
<RiveView hybridRef={setHybridRef} file={riveFile} />
const [setRiveRef, riveRef] = useRive();
riveRef?.play();
riveRef?.pause();
<Rive ref={setRiveRef} url="..." />
See Rive ref methods for more information.
These methods are deprecated. Migrate to data binding
instead.
New Runtime
Legacy Runtime
riveViewRef?.setNumberInputValue('level', 5);
riveViewRef?.setBooleanInputValue('isActive', true);
riveViewRef?.triggerInput('buttonPressed');
riveRef.current?.setInputState('State Machine 1', 'level', 5);
riveRef.current?.setInputState('State Machine 1', 'isActive', true);
riveRef.current?.fireState('State Machine 1', 'buttonPressed');
See state machine inputs for more information.
7. Rive Events (Deprecated)
New Runtime
Legacy Runtime
useEffect(() => {
const handleEvent = (event: RiveEvent) => console.log(event);
riveViewRef?.onEventListener(handleEvent);
return () => riveViewRef?.removeEventListeners();
}, [riveViewRef]);
<Rive
onRiveEventReceived={(event) => console.log(event)}
url="..."
/>
See runtime events for more information.
8. Data Binding
The new runtime significantly improves data binding by giving you direct access to ViewModelInstance objects. This enables:
- Initialization hooks - Set initial property values before rendering with
onInit callback
- Multiple instances - Create and manage multiple view model instances from the same file
- Advanced property types - Full support for lists, images, artboards, and nested view models
- Better React integration - Property hooks integrate seamlessly with React state and lifecycle
Main API changes:
- Property hooks take
viewModelInstance instead of riveRef
- Hooks return objects instead of tuples
- Parameters are swapped:
(path, viewModelInstance) vs (riveRef, path)
New Runtime
Legacy Runtime
const { riveFile } = useRiveFile(require('./animation.riv'));
const viewModelInstance = useViewModelInstance(riveFile);
const { value: health, setValue: setHealth } = useRiveNumber('health', viewModelInstance);
const { value: name, setValue: setName } = useRiveString('Player/Name', viewModelInstance);
const { trigger } = useRiveTrigger('gameOver', viewModelInstance, {
onTrigger: () => console.log('Game Over!')
});
<RiveView file={riveFile} dataBind={viewModelInstance} />
const [setRiveRef, riveRef] = useRive();
const [health, setHealth] = useRiveNumber(riveRef, 'health');
const [name, setName] = useRiveString(riveRef, 'Player/Name');
useRiveTrigger(riveRef, 'gameOver', () => console.log('Game Over!'));
<Rive ref={setRiveRef} resourceName="animation" dataBinding={AutoBind(true)} />
See data binding for more information.
9. Out of Band Assets
New Runtime
Legacy Runtime
const { riveFile } = useRiveFile(
require('./animation.riv'),
{
referencedAssets: {
'Inter-594377': {
source: require('./fonts/Inter-594377.ttf'),
},
'my-image': {
source: { uri: 'https://example.com/image.png' },
},
},
}
);
<Rive
url="..."
referencedAssets={{
'Inter-594377': {
source: require('./fonts/Inter-594377.ttf'),
},
}}
/>
See loading assets for more information.
10. Text Run Updates (Deprecated)
Direct text run methods (.setTextRunValue(), .getTextRunValue()) are
deprecated. Migrate to data binding strings instead.
const { value: playerName, setValue: setPlayerName } = useRiveString('playerName', viewModelInstance);
setPlayerName('John Doe');
// The new runtime still supports text run methods like the old runtime
riveViewRef?.setTextRunValue('playerName', 'John Doe');
const name = riveViewRef?.getTextRunValue('playerName');
riveRef.current?.setTextRunValue('playerName', 'John Doe');
See text runs for more information.
11. Callbacks
New Runtime
Legacy Runtime
<RiveView
file={riveFile}
onError={(error) => console.error('Rive error:', error)}
/>
// For state changes, use data binding listeners. For example, a trigger:
const { trigger } = useRiveTrigger('onStateChange', viewModelInstance, {
onTrigger: () => console.log('State changed')
});
<Rive
onPlay={(name, isSM) => console.log('Playing:', name)}
onPause={(name, isSM) => console.log('Paused:', name)}
onStateChanged={(sm, state) => console.log('State changed:', state)}
onError={(error) => console.error('Error:', error)}
/>
See data binding for more information.
Getting Help
If you encounter issues:
- Check the new runtime documentation
- Review the Data Binding guide
- See the example app
- Visit the Rive community forums
- Report issues on GitHub