Skip to content

API design

Miklós Fazekas edited this page Nov 17, 2025 · 25 revisions

Suggested changes to current api:

  1. #23. Allow RiveView to receive dataBind as prop instead of procedural ref.bindViewModelInstance. Also allow to query the bound view model instance with getViewModelInstance.
  2. POC #19 Suspense:
    1. create <RiveContext. Within the Context useRiveFile from the same input could be cached. This would support both Suspense, and placing multiple rive view's to a list. Would also allow us to release memory of objects created by hooks within this context.
    2. Suspense version of useRiveFile which requires to be called from context. We can keep the current non suspense version, but would use the Suspense in most of the examples.
  3. #17 Decided to delay Allow RiveView file prop to be either a RiveFile or a RiveFileInput (uri, require(..), bytearray)
  4. Feature: allow RiveView to write view model properties with prop updates: <RiveView values={Game: {RemainingTime: remainingTime}}}... >
  5. Feature: allow RiveView to listen to to view model properties changes with props: <RiveView listenToValueChange={Foo:{ Bar: (newValue) => console.log("value updated", newValue)}} /> or <RiveView onValueChange={(propName, newValue) => console.log(...) >
  6. Question: autoBind is that needed?! If user provides vmi binding, then we don't do autoBind, otherwise what choice we have?!

DRAFT

Use suspense

Since nitro view is new arch, let's build on newer features from react, like suspense

See useLoader hook from r3f source

Everything should have an easy access on RiveView

Allow RiveView file prop to be either a RiveFile or a RiveFileInput

<RivePlayer 
   file={{url:'https://cdn.rive.app/animations/vehicles.riv'}}
 />

or (with suspense)

const file = useRiveFile({url: 'https://cdn.rive.app/animations/vehicles.riv'}}
<RivePlayer 
   file={file}
 />

RiveContext

Note: Since suspense requires a cache, we don't want a global cache we'll need a <RiveContext>

const MyRiveComponent() {
  const file = useRiveFile({url: 'https://cdn.rive.app/animations/vehicles.riv'}}
  return (
    <RivePlayer 
      file={file}
    />
  )
}
...
<RiveContext>
  <MyRiveComponent />
</RiveContext>

Obsolete Not sure about

Asset loader basic/vs advanced

<RivePlayer 
   file={{url:'https://cdn.rive.app/animations/vehicles.riv'}}
   customAssetLoader={{foo: require('....png'), bar: require('...png')}
 />

or

const file = useRiveFile({url: 'https://cdn.rive.app/animations/vehicles.riv'}, {customAssetLoader: {foo: require('....png'), bar: require('...png')}}
// suspense: type file of file is `RiveFile` not `RiveFile | null`
<RivePlayer 
   file={file}
 />

Binding / Properties

const [score, setScore] = useState()

<RivePlayer 
   file={{url:'https://cdn.rive.app/animations/vehicles.riv'}}
   values={{['Button/State_1']: 'button name'}}
   observeValues={{score: setScore}}
 />

Limitations: only set + listen, but no read

Manual set/get/listen

const file = useRiveFile({url: 'https://cdn.rive.app/animations/vehicles.riv'}, {customAssetLoader: {foo: require('....png'), bar: require('...png')}}
const numSkin = useMemo(() => file.riveNumber('numSkin'), [file])

useEffect(() => numSkin.listen(i => console.log('numSkin is',i))

<RivePlayer 
   file={file}
   state={state}
 />
<Button title="Bump" onPress={() => numSkin.set(numSkim.get() + 1))}

listen + set

const file = useRiveFile({url: 'https://cdn.rive.app/animations/vehicles.riv'}, {customAssetLoader: {foo: require('....png'), bar: require('...png')}}
const [numSkin, setNumSkin] = useRiveNumber(file, 'numSkin')

<RivePlayer 
   file={file}
   state={state}
 />
<Button title="Bump" onPress={() => numSkin.set(numSkim.get() + 1))}

Questions

  1. Is this summary correct?
RiveFile (.riv)
├── Artboard(s) [multiple, one default]
│   ├── StateMachine(s) [multiple, one default] // has ViewModelInstance bound
│   └── Graphics/Animations
├── ViewModel(s) [multiple, one default]
│   └── ViewModelInstance(s)
│       └── Properties [read/observed/set values]
└── Assets [fonts, images, audio] // either provided on load, or referenced and changed later

RivePlayer manages playback of a state machine in an artboard, with a view model instance bound to that state machine.
  1. ViewModelInstance autobinding?! Do ViewModels describe initial values?