From f9e8b0c5d92efcf11a2ddafed28e9402642e8bb9 Mon Sep 17 00:00:00 2001 From: b3hr4d Date: Wed, 21 Feb 2024 11:09:18 +0300 Subject: [PATCH] Add actor hooks for interacting with actors in IC projects --- packages/react/src/helpers/actor.ts | 19 ++++- packages/react/src/provider/actor/index.tsx | 85 +++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/packages/react/src/helpers/actor.ts b/packages/react/src/helpers/actor.ts index 88ca3fe655..4dbc560d4a 100644 --- a/packages/react/src/helpers/actor.ts +++ b/packages/react/src/helpers/actor.ts @@ -30,7 +30,23 @@ const DEFAULT_STATE: ActorCallState = { error: undefined, loading: false, } - +/** + * Provides a set of React hooks designed for interacting with actors in an Internet Computer (IC) project using the React framework and Zustand for state management. + * + * @param actorManager An instance of ActorManager containing methods and properties to manage actors, including the actorStore, canisterId, visitFunction, callMethod, and initialize function. + * @returns An object containing several hooks and utility functions for interacting with actors, managing state, and invoking actor methods. + * + * Hooks included: + * - initialize: Function to initialize actor management. + * - useActorState: Hook for accessing the actor's state including the canister ID. + * - useVisitMethod: Hook for memoizing a method visit service for a given actor method name. + * - useReactorCall: Hook for making calls to actor methods with support for loading states, errors, and custom event handlers. + * - useQueryCall: Hook specifically designed for query calls to actors with features such as automatic refetching on mount and at specified intervals. + * - useUpdateCall: Alias for useReactorCall, tailored for update calls to actors. + * - useMethodCall: Combines useVisitMethod and useReactorCall for a streamlined experience when calling actor methods, including visitation and state management. + * + * Each hook is designed to simplify the process of interacting with actors in IC projects by abstracting away the complexity of state management, error handling, and method invocation. + */ export const getActorHooks = ( actorManager: ActorManager ): ActorHooks => { @@ -47,6 +63,7 @@ export const getActorHooks = ( ): VisitService[M] => { return useMemo(() => visitFunction[functionName], [functionName]) } + const useReactorCall: ReactorCall = ({ args = [], functionName, diff --git a/packages/react/src/provider/actor/index.tsx b/packages/react/src/provider/actor/index.tsx index 2427eb3efc..9b62bdf0ab 100644 --- a/packages/react/src/provider/actor/index.tsx +++ b/packages/react/src/provider/actor/index.tsx @@ -82,20 +82,105 @@ export function createReactorContext({ const initialize = () => useActorContext().initialize() + /** + * Hook for accessing the current state of the actor, including the canister ID. + * + * @returns An object containing the current state of the actor from Zustand's store and the canister ID. + * @example + * ```tsx + * function ActorStateComponent() { + * const { canisterId, initializing, error, initialized } = useActorState(); + * + * return ( + *
+ *

Canister ID: {canisterId}

+ *

Initializing: {initializing.toString()}

+ *

Initialized: {initialized.toString()}

+ *

Error: {error?.message}

+ *
+ * ); + * } + *``` + */ const useActorState = () => useActorContext().useActorState() + /** + * Hook for making query calls to actors. It supports automatic refetching on component mount and at specified intervals. + * + * @param options Configuration object for the query call, including refetching options and other configurations passed to useReactorCall. + * @returns An object containing the query call function and the current call state (data, error, loading, call, reset). + * @example + * ```tsx + * function QueryCallComponent() { + * const { call, data, loading } = useQueryCall({ + * functionName: 'getUserProfile', + * args: ['123'], + * refetchOnMount: true, + * refetchInterval: 5000, // refetch every 5 seconds + * }); + * + * if (loading) return

Loading profile...

; + * + * return ( + *
+ *

User Profile: {JSON.stringify(data)}

+ * + *
+ * ); + * } + * ``` + */ const useQueryCall = >( args: UseQueryCallArgs ) => useActorContext().useQueryCall(args) + /** + * Hook for making update calls to actors, handling loading states, and managing errors. It supports custom event handlers for loading, success, and error events. + * + * @param options Configuration object for the actor method call, including the method name, arguments, and event handlers. + * @returns An object containing the method call function, a reset function to reset the call state to its default, and the current call state (data, error, loading, call, reset). + * @example + * ```tsx + * function UpdateCallComponent() { + * const { call, data, loading } = useUpdateCall({ + * functionName: 'updateUserProfile', + * args: ['123', { name: 'John Doe' }], + * onLoading: (loading) => console.log('Loading:', loading), + * onError: (error) => console.error('Error:', error), + * onSuccess: (data) => console.log('Success:', data), + * }); + * + * if (loading) return

Updating profile...

; + * + * return ( + *
+ *

Updated Profile: {JSON.stringify(data)}

+ * + *
+ * ); + * } + * ``` + */ const useUpdateCall = >( args: UseUpdateCallArgs ) => useActorContext().useUpdateCall(args) + /** + * Hook that combines useVisitMethod and useReactorCall for calling actor methods. It provides both the visit service for the method and the ability to make actor calls with state management. + * + * @param args Configuration object including the function name and arguments for the actor method call. + * @returns An object containing the visit function for the method and the current call state (data, error, loading). + */ const useMethodCall = >( args: UseMethodCallArg ) => useActorContext().useMethodCall(args) + /** + * Memoizes and returns a visit service function for a specific actor method. + * + * @param functionName The name of the actor method to visit. + * @returns The visit service function for the specified method. + */ const useVisitMethod = (functionName: FunctionName) => useActorContext().useVisitMethod(functionName)