hook with generic

This commit is contained in:
Hernan Torrisi
2025-01-08 08:03:40 -08:00
parent f11d17bf3e
commit 2f0c32c138
4 changed files with 153 additions and 5 deletions

View File

@@ -54,7 +54,7 @@ export default function useViewModel(
function setInstance(instance: ViewModelInstance | null) {
setViewModelInstance(instance);
rive!.setDataContextFromInstance(instance);
rive!.bindViewModelInstance(instance);
currentParams.current = parameters;
}
function getViewModelInstance(): ViewModelInstance | null {

View File

@@ -30,7 +30,6 @@ const equal = (
params.rive !== to.parameters.rive ||
params.viewModelInstance !== to.parameters.viewModelInstance
) {
console.log('paso 3');
return false;
}
return true;

View File

@@ -0,0 +1,112 @@
import { useState, useEffect, useRef } from 'react';
import {
EventType,
ViewModelInstance,
} from '@rive-app/canvas';
import {
UseViewModelInstancePropertyType,
AcceptedVieModelType,
} from '../types';
import useViewModelInstanceProperty from './useViewModelInstanceProperty';
import { DataType } from '@rive-app/canvas/rive_advanced.mjs';
const defaultParams: UseViewModelInstancePropertyType = {
viewModelInstance: null,
};
const equal = <U extends UseViewModelInstancePropertyType>(
name: string,
params: U | null,
viewModelInstance: ViewModelInstance | null,
to: HookArguments | null
): boolean => {
if (!params || !to) {
return false;
}
if (
params.initialValue !== to.parameters.initialValue ||
name !== to.name ||
viewModelInstance !== to.viewModelInstance
) {
return false;
}
return true;
};
type HookArguments = {
name: string;
parameters: UseViewModelInstancePropertyType;
viewModelInstance: ViewModelInstance | null;
};
/**
* Custom hook for fetching a view model instance value.
*
* @param name - name of the propery
* @param path - Path to reach the required property
* @param userParameters - Parameters to load view model instance number
* @returns
*/
export default function useViewModelProperty<
T extends UseViewModelInstancePropertyType,
U extends AcceptedVieModelType<T>
>(name: string, path: string[] = [], userParameters?: T): U | null {
const [viewModel, setViewModelValue] = useState<AcceptedVieModelType<T> | null>(null);
const currentArguments = useRef<HookArguments | null>(null);
const viewModelInstance = useViewModelInstanceProperty(path, userParameters);
useEffect(() => {
const parameters: T = {
...defaultParams,
...(userParameters as T),
};
function getVMI(name: string): U | null {
const properties = viewModelInstance!.properties;
const propData = properties.find((value) => value.name === name);
if (propData === null) {
return null;
}
if (propData!.type === DataType.number) {
return viewModelInstance!.number(name) as U;
} else if (propData!.type === DataType.string) {
return viewModelInstance!.string(name) as U;
} else if (propData!.type === DataType.boolean) {
return viewModelInstance!.boolean(name) as U;
} else if (propData!.type === DataType.color) {
return viewModelInstance!.color(name) as U;
}
return null;
}
function setInitialValue(property: U, params: T) {
if (params.initialValue !== undefined) {
property.value = params.initialValue;
}
}
function searchViewModelValue() {
const instanceValue = getVMI(name);
if (instanceValue !== null) {
setInitialValue(instanceValue, parameters);
}
setViewModelValue(instanceValue);
currentArguments.current = {
parameters,
name,
viewModelInstance,
};
}
if (!equal(name, parameters, viewModelInstance, currentArguments.current)) {
parameters.rive?.on(EventType.Load, searchViewModelValue);
searchViewModelValue();
}
return () => {
parameters.rive?.off(EventType.Load, searchViewModelValue);
};
}, [name, userParameters, viewModelInstance]);
return viewModel as U;
}

View File

@@ -4,6 +4,10 @@ import {
RiveFileParameters,
RiveParameters,
ViewModelInstance,
ViewModelInstanceBoolean,
ViewModelInstanceNumber,
ViewModelInstanceString,
ViewModelInstanceColor,
} from '@rive-app/canvas';
import { ComponentProps, RefCallback } from 'react';
@@ -75,6 +79,39 @@ export type UseViewModelInstanceValueParameters = {
rive?: Rive | null;
};
export type UseViewModelInstanceNumberParameters = UseViewModelInstanceValueParameters & {
initialValue?: number;
};
export type UseViewModelInstanceNumberParameters =
UseViewModelInstanceValueParameters & {
initialValue?: number;
};
export type UseViewModelInstanceStringParameters =
UseViewModelInstanceValueParameters & {
initialValue?: string;
};
export type UseViewModelInstanceBooleanParameters =
UseViewModelInstanceValueParameters & {
initialValue?: boolean;
};
export type UseViewModelInstanceColorParameters =
UseViewModelInstanceValueParameters & {
initialValue?: number;
};
export type UseViewModelInstancePropertyType =
| UseViewModelInstanceNumberParameters
| UseViewModelInstanceStringParameters
| UseViewModelInstanceBooleanParameters
| UseViewModelInstanceColorParameters;
export type AcceptedVieModelType<T> =
T extends UseViewModelInstanceNumberParameters
? ViewModelInstanceNumber
: T extends UseViewModelInstanceStringParameters
? ViewModelInstanceString
: T extends UseViewModelInstanceBooleanParameters
? ViewModelInstanceBoolean
: T extends UseViewModelInstanceColorParameters
? ViewModelInstanceColor
: never;