UNPKG

@apollo/client

Version:

A fully-featured caching GraphQL client.

271 lines (270 loc) 12.4 kB
import type { TypedDocumentNode } from "@graphql-typed-document-node/core"; import type { DocumentNode } from "graphql"; import type { ApolloClient, DefaultContext, ErrorLike, ErrorPolicy, FetchPolicy, OperationVariables } from "@apollo/client"; import type { MaybeMasked } from "@apollo/client/masking"; import type { DocumentationTypes as UtilityDocumentationTypes } from "@apollo/client/utilities/internal"; import type { NoInfer, VariablesOption } from "@apollo/client/utilities/internal"; export declare namespace useSubscription { import _self = useSubscription; namespace Base { interface Options<TData = unknown, TVariables extends OperationVariables = OperationVariables> { /** * How you want your component to interact with the Apollo cache. For details, see [Setting a fetch policy](https://www.apollographql.com/docs/react/data/queries/#setting-a-fetch-policy). */ fetchPolicy?: FetchPolicy; /** * Specifies the `ErrorPolicy` to be used for this operation */ errorPolicy?: ErrorPolicy; /** * Determines if your subscription should be unsubscribed and subscribed again when an input to the hook (such as `subscription` or `variables`) changes. */ shouldResubscribe?: boolean | ((options: Options<TData, TVariables>) => boolean); /** * An `ApolloClient` instance. By default `useSubscription` / `Subscription` uses the client passed down via context, but a different client can be passed in. */ client?: ApolloClient; /** * Determines if the current subscription should be skipped. Useful if, for example, variables depend on previous queries and are not ready yet. */ skip?: boolean; /** * Shared context between your component and your network interface (Apollo Link). */ context?: DefaultContext; /** * Shared context between your component and your network interface (Apollo Link). */ extensions?: Record<string, any>; /** * Allows the registration of a callback function that will be triggered each time the `useSubscription` Hook / `Subscription` component completes the subscription. */ onComplete?: () => void; /** * Allows the registration of a callback function that will be triggered each time the `useSubscription` Hook / `Subscription` component receives data. The callback `options` object param consists of the current Apollo Client instance in `client`, and the received subscription data in `data`. */ onData?: (options: OnDataOptions<TData>) => any; /** * Allows the registration of a callback function that will be triggered each time the `useSubscription` Hook / `Subscription` component receives an error. */ onError?: (error: ErrorLike) => void; /** * If `true`, the hook will not cause the component to rerender. This is useful when you want to control the rendering of your component yourself with logic in the `onData` and `onError` callbacks. * * Changing this to `true` when the hook already has `data` will reset the `data` to `undefined`. * * @defaultValue `false` */ ignoreResults?: boolean; } } type Options<TData = unknown, TVariables extends OperationVariables = OperationVariables> = Base.Options<TData, TVariables> & VariablesOption<TVariables>; namespace DocumentationTypes { namespace useSubscription { interface Options<TData = unknown, TVariables extends OperationVariables = OperationVariables> extends Base.Options<TData, TVariables>, UtilityDocumentationTypes.VariableOptions<TVariables> { } } } interface Result<TData = unknown> { /** * A boolean that indicates whether any initial data has been returned */ loading: boolean; /** * An object containing the result of your GraphQL subscription. Defaults to an empty object. */ data?: MaybeMasked<TData>; /** * A runtime error with `graphQLErrors` and `networkError` properties */ error?: ErrorLike; /** * A function that when called will disconnect and reconnect the connection * to the subscription. If the subscription is deduplicated, this will * restart the connection for all deduplicated subscriptions. */ restart: () => void; } namespace DocumentationTypes { namespace useSubscription { interface Result<TData = unknown> extends _self.Result<TData> { } } } namespace DocumentationTypes { /** * > Refer to the [Subscriptions](https://www.apollographql.com/docs/react/data/subscriptions/) section for a more in-depth overview of `useSubscription`. * * @example * * ```jsx * const COMMENTS_SUBSCRIPTION = gql` * subscription OnCommentAdded($repoFullName: String!) { * commentAdded(repoFullName: $repoFullName) { * id * content * } * } * `; * * function DontReadTheComments({ repoFullName }) { * const { * data: { commentAdded }, * loading, * } = useSubscription(COMMENTS_SUBSCRIPTION, { variables: { repoFullName } }); * return <h4>New comment: {!loading && commentAdded.content}</h4>; * } * ``` * * @remarks * * #### Consider using `onData` instead of `useEffect` * * If you want to react to incoming data, please use the `onData` option instead of `useEffect`. * State updates you make inside a `useEffect` hook might cause additional rerenders, and `useEffect` is mostly meant for side effects of rendering, not as an event handler. * State updates made in an event handler like `onData` might - depending on the React version - be batched and cause only a single rerender. * * Consider the following component: * * ```jsx * export function Subscriptions() { * const { data, error, loading } = useSubscription(query); * const [accumulatedData, setAccumulatedData] = useState([]); * * useEffect(() => { * setAccumulatedData((prev) => [...prev, data]); * }, [data]); * * return ( * <> * {loading && <p>Loading...</p>} * {JSON.stringify(accumulatedData, undefined, 2)} * </> * ); * } * ``` * * Instead of using `useEffect` here, we can re-write this component to use the `onData` callback function accepted in `useSubscription`'s `options` object: * * ```jsx * export function Subscriptions() { * const [accumulatedData, setAccumulatedData] = useState([]); * const { data, error, loading } = useSubscription(query, { * onData({ data }) { * setAccumulatedData((prev) => [...prev, data]); * }, * }); * * return ( * <> * {loading && <p>Loading...</p>} * {JSON.stringify(accumulatedData, undefined, 2)} * </> * ); * } * ``` * * > ⚠️ **Note:** The `useSubscription` option `onData` is available in Apollo Client >= 3.7. In previous versions, the equivalent option is named `onSubscriptionData`. * * Now, the first message will be added to the `accumulatedData` array since `onData` is called _before_ the component re-renders. React 18 automatic batching is still in effect and results in a single re-render, but with `onData` we can guarantee each message received after the component mounts is added to `accumulatedData`. * * @param subscription - A GraphQL subscription document parsed into an AST by `gql`. * @param options - Options to control how the subscription is executed. * @returns Query result object */ function useSubscription<TData = unknown, TVariables extends OperationVariables = OperationVariables>(options?: useSubscription.Options<TData, TVariables>): useSubscription.Result<TData>; } type OnDataResult<TData = unknown> = Omit<Result<TData>, "restart">; interface OnDataOptions<TData = unknown> { client: ApolloClient; data: OnDataResult<TData>; } interface OnSubscriptionDataOptions<TData = unknown> { client: ApolloClient; subscriptionData: OnDataResult<TData>; } } /** * > Refer to the [Subscriptions](https://www.apollographql.com/docs/react/data/subscriptions/) section for a more in-depth overview of `useSubscription`. * * @example * * ```jsx * const COMMENTS_SUBSCRIPTION = gql` * subscription OnCommentAdded($repoFullName: String!) { * commentAdded(repoFullName: $repoFullName) { * id * content * } * } * `; * * function DontReadTheComments({ repoFullName }) { * const { * data: { commentAdded }, * loading, * } = useSubscription(COMMENTS_SUBSCRIPTION, { variables: { repoFullName } }); * return <h4>New comment: {!loading && commentAdded.content}</h4>; * } * ``` * * @remarks * * #### Consider using `onData` instead of `useEffect` * * If you want to react to incoming data, please use the `onData` option instead of `useEffect`. * State updates you make inside a `useEffect` hook might cause additional rerenders, and `useEffect` is mostly meant for side effects of rendering, not as an event handler. * State updates made in an event handler like `onData` might - depending on the React version - be batched and cause only a single rerender. * * Consider the following component: * * ```jsx * export function Subscriptions() { * const { data, error, loading } = useSubscription(query); * const [accumulatedData, setAccumulatedData] = useState([]); * * useEffect(() => { * setAccumulatedData((prev) => [...prev, data]); * }, [data]); * * return ( * <> * {loading && <p>Loading...</p>} * {JSON.stringify(accumulatedData, undefined, 2)} * </> * ); * } * ``` * * Instead of using `useEffect` here, we can re-write this component to use the `onData` callback function accepted in `useSubscription`'s `options` object: * * ```jsx * export function Subscriptions() { * const [accumulatedData, setAccumulatedData] = useState([]); * const { data, error, loading } = useSubscription(query, { * onData({ data }) { * setAccumulatedData((prev) => [...prev, data]); * }, * }); * * return ( * <> * {loading && <p>Loading...</p>} * {JSON.stringify(accumulatedData, undefined, 2)} * </> * ); * } * ``` * * > ⚠️ **Note:** The `useSubscription` option `onData` is available in Apollo Client >= 3.7. In previous versions, the equivalent option is named `onSubscriptionData`. * * Now, the first message will be added to the `accumulatedData` array since `onData` is called _before_ the component re-renders. React 18 automatic batching is still in effect and results in a single re-render, but with `onData` we can guarantee each message received after the component mounts is added to `accumulatedData`. * * @param subscription - A GraphQL subscription document parsed into an AST by `gql`. * @param options - Options to control how the subscription is executed. * @returns Query result object */ export declare function useSubscription<TData = unknown, TVariables extends OperationVariables = OperationVariables>(subscription: DocumentNode | TypedDocumentNode<TData, TVariables>, ...[options]: {} extends (TVariables) ? [ options?: useSubscription.Options<NoInfer<TData>, NoInfer<TVariables>> ] : [options: useSubscription.Options<NoInfer<TData>, NoInfer<TVariables>>]): useSubscription.Result<TData>; //# sourceMappingURL=useSubscription.d.ts.map