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( diff --git a/example/__tests__/autoplay.harness.tsx b/example/__tests__/autoplay.harness.tsx index 1583a646..e8323b99 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,78 @@ describe('autoPlay prop (issue #138)', () => { cleanup(); }); }); + +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); + + 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 00000000..b9772788 Binary files /dev/null and b/example/assets/rive/nodefaultbouncing.riv differ