import { useMemo } from "react" import { QueryKey, useQuery, QueryObserverOptions, UseQueryResult, } from "@tanstack/react-query" import { FunctionName, Reactor, TransformKey, ReactorArgs, ReactorReturnOk, ReactorReturnErr, } from "@ic-reactor/core" import { CallConfig } from "@icp-sdk/core/agent" export interface UseActorQueryParameters< A, M extends FunctionName, T extends TransformKey = "candid", TSelected = ReactorReturnOk, > extends Omit< QueryObserverOptions< ReactorReturnOk, ReactorReturnErr, TSelected, ReactorReturnOk, QueryKey >, "queryKey" | "queryFn" > { reactor: Reactor functionName: M args?: ReactorArgs callConfig?: CallConfig queryKey?: QueryKey } export type UseActorQueryConfig< A, M extends FunctionName, T extends TransformKey = "candid", TSelected = ReactorReturnOk, > = Omit, "reactor"> export type UseActorQueryResult< A, M extends FunctionName, T extends TransformKey = "candid", TSelected = ReactorReturnOk, > = UseQueryResult> /** * Hook for executing query calls on a canister. * * @example * const { data, isLoading } = useActorQuery({ * reactor, * functionName: "getUser", * args: ["user-123"], * }) * * // With select transformation * const { data } = useActorQuery({ * reactor, * functionName: "getUser", * args: ["user-123"], * select: (user) => user.name, * }) */ export const useActorQuery = < A, M extends FunctionName, T extends TransformKey = "candid", TSelected = ReactorReturnOk, >({ reactor, functionName, args, callConfig, queryKey: defaultQueryKey, ...options }: UseActorQueryParameters): UseActorQueryResult< A, M, T, TSelected > => { // Memoize query options to prevent unnecessary re-computations const { queryKey, queryFn } = useMemo( () => reactor.getQueryOptions({ callConfig, functionName, args, queryKey: defaultQueryKey, }), [reactor, callConfig, functionName, args, defaultQueryKey] ) return useQuery( { queryFn, ...options, queryKey, }, reactor.queryClient ) }