import { UNASSIGNED_STATE, useUpdatableDisposableState, } from '@isograph/react-disposable-state'; import type { NetworkResponseObject } from '../core/cache'; import type { FetchOptions } from '../core/check'; import { type RequiredFetchOptions } from '../core/check'; import type { IsographEntrypoint } from '../core/entrypoint'; import { type NormalizationAst, type NormalizationAstLoader, } from '../core/entrypoint'; import type { ExtractParameters, FragmentReference, } from '../core/FragmentReference'; import { type UnknownTReadFromStore } from '../core/FragmentReference'; import { getOrLoadReaderWithRefetchQueries, ROOT_ID, } from '../core/IsographEnvironment'; import { maybeMakeNetworkRequest } from '../core/makeNetworkRequest'; import { useIsographEnvironment } from './IsographEnvironmentProvider'; export type UseImperativeReferenceResult< TReadFromStore extends UnknownTReadFromStore, TClientFieldValue, TNormalizationAst extends NormalizationAst | NormalizationAstLoader, TRawResponseType, > = { fragmentReference: FragmentReference< TReadFromStore, TClientFieldValue > | null; loadFragmentReference: ( variables: ExtractParameters, ...[fetchOptions]: NormalizationAstLoader extends TNormalizationAst ? [fetchOptions: RequiredFetchOptions] : [fetchOptions?: FetchOptions] ) => void; }; export function useImperativeReference< TReadFromStore extends UnknownTReadFromStore, TClientFieldValue, TNormalizationAst extends NormalizationAst | NormalizationAstLoader, TRawResponseType extends NetworkResponseObject, >( entrypoint: IsographEntrypoint< TReadFromStore, TClientFieldValue, TNormalizationAst, TRawResponseType >, ): UseImperativeReferenceResult< TReadFromStore, TClientFieldValue, TNormalizationAst, TRawResponseType > { const { state, setState } = useUpdatableDisposableState< FragmentReference >(); const environment = useIsographEnvironment(); return { fragmentReference: state !== UNASSIGNED_STATE ? state : null, loadFragmentReference: ( variables: ExtractParameters, fetchOptions?: FetchOptions, ) => { const { fieldName, readerArtifactKind, readerWithRefetchQueries } = getOrLoadReaderWithRefetchQueries( environment, entrypoint.readerWithRefetchQueries, ); const [networkRequest, disposeNetworkRequest] = maybeMakeNetworkRequest( environment, entrypoint, variables, readerWithRefetchQueries, fetchOptions ?? null, ); setState([ { kind: 'FragmentReference', readerWithRefetchQueries, fieldName, readerArtifactKind, root: { __link: ROOT_ID, __typename: entrypoint.concreteType }, variables, networkRequest, }, () => { disposeNetworkRequest(); }, ]); }, }; }