Skip to content

Commit a4a993a

Browse files
authored
feat: add functional updater support to setValue (#92)
Allows setValue to accept a function that receives the previous value, similar to React's setState pattern. ```ts setValue((v) => (v ?? 0) + 5) ```
1 parent b790796 commit a4a993a

4 files changed

Lines changed: 33 additions & 9 deletions

File tree

src/hooks/useRiveColor.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@ import type {
33
ViewModelColorProperty,
44
ViewModelInstance,
55
} from '../specs/ViewModel.nitro';
6-
import { type UseRivePropertyResult } from '../types';
76
import { useRiveProperty } from './useRiveProperty';
87
import { RiveColor } from '../core/RiveColor';
98

109
const COLOR_PROPERTY_OPTIONS = {
1110
getProperty: (vmi: ViewModelInstance, p: string) => vmi.colorProperty(p),
1211
};
1312

13+
export interface UseRiveColorResult {
14+
value: RiveColor | undefined;
15+
setValue: (value: RiveColor | string) => void;
16+
error: Error | null;
17+
}
18+
1419
/**
1520
* Hook for interacting with color ViewModel instance properties.
1621
*
@@ -21,9 +26,7 @@ const COLOR_PROPERTY_OPTIONS = {
2126
export function useRiveColor(
2227
path: string,
2328
viewModelInstance?: ViewModelInstance | null
24-
): UseRivePropertyResult<RiveColor> & {
25-
setValue: (value: RiveColor | string) => void;
26-
} {
29+
): UseRiveColorResult {
2730
const [rawValue, setRawValue, error] = useRiveProperty<
2831
ViewModelColorProperty,
2932
number

src/hooks/useRiveProperty.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
2828
/** Optional override callback for property events (mainly used by triggers) */
2929
onPropertyEventOverride?: (...args: any[]) => void;
3030
}
31-
): [T | undefined, (value: T) => void, Error | null, P | undefined] {
31+
): [
32+
T | undefined,
33+
(value: T | ((prevValue: T | undefined) => T)) => void,
34+
Error | null,
35+
P | undefined,
36+
] {
3237
const [value, setValue] = useState<T | undefined>(undefined);
3338
const [error, setError] = useState<Error | null>(null);
3439

@@ -79,14 +84,20 @@ export function useRiveProperty<P extends ViewModelProperty, T>(
7984

8085
// Set the value of the property
8186
const setPropertyValue = useCallback(
82-
(newValue: T) => {
87+
(valueOrUpdater: T | ((prevValue: T | undefined) => T)) => {
8388
if (!property) {
8489
setError(
8590
new Error(
8691
`Cannot set value for property "${path}" because it was not found. Your view model instance may be undefined, or the path may be incorrect.`
8792
)
8893
);
8994
} else {
95+
const newValue =
96+
typeof valueOrUpdater === 'function'
97+
? (valueOrUpdater as (prevValue: T | undefined) => T)(
98+
property.value
99+
)
100+
: valueOrUpdater;
90101
property.value = newValue;
91102
}
92103
},

src/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ export { useRiveColor } from './hooks/useRiveColor';
5050
export { useRiveTrigger } from './hooks/useRiveTrigger';
5151
export { useRiveFile } from './hooks/useRiveFile';
5252
export { type RiveFileInput } from './hooks/useRiveFile';
53+
export { type SetValueAction } from './types';
5354
export { DataBindMode };

src/types.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1+
/**
2+
* A value or a function that computes a new value from the previous value.
3+
* Similar to React's SetStateAction pattern.
4+
*/
5+
export type SetValueAction<T> = T | ((prevValue: T | undefined) => T);
6+
17
export interface UseRivePropertyResult<T> {
28
/**
39
* The current value of the property.
410
*/
511
value: T | undefined;
612
/**
7-
* Set the value of the property.
8-
* @param value - The value to set the property to.
13+
* Set the value of the property. Accepts either a direct value or
14+
* a function that receives the previous value and returns the new value.
15+
* @example
16+
* setValue(10) // Set to 10
17+
* setValue((prev) => (prev ?? 0) + 5) // Increment by 5
918
*/
10-
setValue: (value: T) => void;
19+
setValue: (value: SetValueAction<T>) => void;
1120
/**
1221
* The error if the property is not found.
1322
*/

0 commit comments

Comments
 (0)