Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/hooks/useRiveProperty.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
import {
type ObservableProperty,
type ViewModelInstance,
Expand Down Expand Up @@ -35,6 +35,12 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
Error | null,
P | undefined,
] {
// Store the callback in a ref so identity changes don't cause property
// disposal/re-creation. The listener always calls through the ref,
// ensuring the latest callback is invoked without re-subscribing.
const onPropertyEventOverrideRef = useRef(options.onPropertyEventOverride);
onPropertyEventOverrideRef.current = options.onPropertyEventOverride;

const property = useDisposableMemo(
() => {
if (!viewModelInstance) return undefined;
Expand All @@ -44,7 +50,7 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
) as unknown as ObservableViewModelProperty<T>;
},
(p) => p?.dispose(),
[options, viewModelInstance, path]
[viewModelInstance, path]
);

// Always start undefined — the listener delivers the current value as its first emission.
Expand Down Expand Up @@ -75,12 +81,14 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
// undefined → value without waiting for a property change.
// (Legacy addListener does NOT emit on subscribe — only on changes.
// Experimental valueStream emits the current value as its first element.)
if (!options.onPropertyEventOverride) {
if (!onPropertyEventOverrideRef.current) {
setValue(property.value);
}

const removeListener = options.onPropertyEventOverride
? property.addListener(options.onPropertyEventOverride)
const removeListener = onPropertyEventOverrideRef.current
? property.addListener((...args: any[]) => {
onPropertyEventOverrideRef.current?.(...args);
})
: property.addListener((newValue) => {
setValue(newValue);
});
Expand All @@ -93,7 +101,7 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
// Native dispose() handles listener cleanup, so this is safe to ignore.
}
};
}, [options, property]);
}, [property]);

// Set the value of the property (no-op if property isn't available yet).
// Uses tracked `value` from state for updater functions — avoids a synchronous
Expand Down
15 changes: 5 additions & 10 deletions src/hooks/useRiveTrigger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo } from 'react';
import { useCallback } from 'react';
import {
type ViewModelInstance,
type ViewModelTriggerProperty,
Expand Down Expand Up @@ -26,18 +26,13 @@ export function useRiveTrigger(
): UseRiveTriggerResult {
const { onTrigger } = params ?? {};

const triggerOptions = useMemo(
() => ({
getProperty: getTriggerProperty,
onPropertyEventOverride: onTrigger,
}),
[onTrigger]
);

const [_, __, error, property] = useRiveProperty<
ViewModelTriggerProperty,
undefined
>(viewModelInstance, path, triggerOptions);
>(viewModelInstance, path, {
getProperty: getTriggerProperty,
onPropertyEventOverride: onTrigger,
});

const trigger = useCallback(() => {
if (property) {
Expand Down
Loading