From f53aa05440ee0986904d4010a8857ce7c2954418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Mar 2026 14:15:34 +0100 Subject: [PATCH 1/3] fix(android): don't pass autoBind=true when artboard has no default ViewModel --- android/src/main/java/com/rive/RiveReactNativeView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/main/java/com/rive/RiveReactNativeView.kt b/android/src/main/java/com/rive/RiveReactNativeView.kt index 6bd9d89a..7753d936 100644 --- a/android/src/main/java/com/rive/RiveReactNativeView.kt +++ b/android/src/main/java/com/rive/RiveReactNativeView.kt @@ -105,7 +105,7 @@ class RiveReactNativeView(context: ThemedReactContext) : FrameLayout(context) { if (reload) { val hasDataBinding = when (config.bindData) { is BindData.None -> false - is BindData.Auto -> config.riveFile.viewModelCount > 0 + is BindData.Auto -> false is BindData.Instance, is BindData.ByName -> true } riveAnimationView?.setRiveFile( From 192f8a56a77da01660d1e2feb73fc9bf9951cdfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Mar 2026 17:09:51 +0100 Subject: [PATCH 2/3] test: add harness test for Auto dataBind with no default ViewModel --- example/__tests__/autoplay.harness.tsx | 40 ++++++++++++++++++++++ example/assets/rive/nodefaultbouncing.riv | Bin 0 -> 319 bytes 2 files changed, 40 insertions(+) create mode 100644 example/assets/rive/nodefaultbouncing.riv diff --git a/example/__tests__/autoplay.harness.tsx b/example/__tests__/autoplay.harness.tsx index 1583a646..be734f9e 100644 --- a/example/__tests__/autoplay.harness.tsx +++ b/example/__tests__/autoplay.harness.tsx @@ -21,6 +21,10 @@ import type { ViewModelInstance } from '@rive-app/react-native'; // Source: https://rive.app/community/files/25997-48571-demo-for-tracking-rive-property-in-react-native/ const BOUNCING_BALL = require('../assets/rive/bouncing_ball.riv'); +// Simple animation with ViewModels defined but no default ViewModel assigned to the artboard +// Source: https://rive.app/community/files/27026-50856-no-default-vm-for-artboard/ +const NO_DEFAULT_VM = require('../assets/rive/nodefaultbouncing.riv'); + function expectDefined(value: T): asserts value is NonNullable { expect(value).toBeDefined(); } @@ -264,3 +268,39 @@ describe('autoPlay prop (issue #138)', () => { cleanup(); }); }); + +describe('Auto dataBind with no default ViewModel (issue #189)', () => { + it('plays without error when file has ViewModels but no artboard default', async () => { + const file = await RiveFileFactory.fromSource(NO_DEFAULT_VM, undefined); + + const context: TestContext = { ref: null, error: null }; + await render( + + { + context.ref = ref; + }, + }} + style={{ flex: 1 }} + file={file} + autoPlay={true} + fit={Fit.Contain} + onError={(e) => { + context.error = e.message; + }} + /> + + ); + + await waitFor( + () => { + expect(context.ref).not.toBeNull(); + }, + { timeout: 5000 } + ); + + expect(context.error).toBeNull(); + cleanup(); + }); +}); diff --git a/example/assets/rive/nodefaultbouncing.riv b/example/assets/rive/nodefaultbouncing.riv new file mode 100644 index 0000000000000000000000000000000000000000..b97727880c937a5da899d895821421ac82655b0d GIT binary patch literal 319 zcmZvYJxjxI7{u@C|6+>J3Q`drYL-I4DM~5gTWeGh?4r^=YQTV12&LfezHxUG} zpTONu(f3ej-CW{7-2|WE$8j9@z?~e`4orN%-OHy$GE%Q>vCR&++rAz5i`ji1>NQo$8%7lWP0XwBBnk%K*v!L!@2RFXuY^JcZ zE?6#Rkl&ZX>A$?YmB{j!tNrZ1ez7!n+VC2_RrM~erbXCz5cAl(^FzzQj^1Gxl_ycy HeiYyry|+lg literal 0 HcmV?d00001 From 25c2ff40eaac70a42db5dacd5935f4e16a86369a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Thu, 26 Mar 2026 17:28:23 +0100 Subject: [PATCH 3/3] test: verify Auto dataBind still binds when default ViewModel exists --- example/__tests__/autoplay.harness.tsx | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/example/__tests__/autoplay.harness.tsx b/example/__tests__/autoplay.harness.tsx index be734f9e..e8323b99 100644 --- a/example/__tests__/autoplay.harness.tsx +++ b/example/__tests__/autoplay.harness.tsx @@ -270,6 +270,45 @@ describe('autoPlay prop (issue #138)', () => { }); describe('Auto dataBind with no default ViewModel (issue #189)', () => { + it('auto-binds default ViewModel when one exists', async () => { + const file = await RiveFileFactory.fromSource(BOUNCING_BALL, undefined); + + const context: TestContext = { ref: null, error: null }; + await render( + + { + context.ref = ref; + }, + }} + style={{ flex: 1 }} + file={file} + autoPlay={true} + fit={Fit.Contain} + onError={(e) => { + context.error = e.message; + }} + /> + + ); + + await waitFor( + () => { + expect(context.ref).not.toBeNull(); + }, + { timeout: 5000 } + ); + + expect(context.error).toBeNull(); + + const vmi = context.ref!.getViewModelInstance(); + expect(vmi).not.toBeNull(); + expect(vmi!.numberProperty('ypos')).toBeDefined(); + + cleanup(); + }); + it('plays without error when file has ViewModels but no artboard default', async () => { const file = await RiveFileFactory.fromSource(NO_DEFAULT_VM, undefined);