@apollo/client
Version:
A fully-featured caching GraphQL client.
54 lines • 2.66 kB
JavaScript
import * as React from "react";
import { useDeepMemo, wrapHook } from "./internal/index.js";
import { useApolloClient } from "./useApolloClient.js";
import { useSyncExternalStore } from "./useSyncExternalStore.js";
export function useFragment(options) {
"use no memo";
return wrapHook("useFragment", useFragment_, useApolloClient(options.client))(options);
}
function useFragment_(options) {
const client = useApolloClient(options.client);
const { from, ...rest } = options;
const { cache } = client;
// We calculate the cache id seperately because we don't want changes to non
// key fields in the `from` property to recreate the observable. If the cache
// identifier stays the same between renders, we want to reuse the existing
// subscription.
const ids = useDeepMemo(() => {
const fromArray = Array.isArray(from) ? from : [from];
const ids = fromArray.map((value) => typeof value === "string" ? value
: value === null ? null
: cache.identify(value));
return Array.isArray(from) ? ids : ids[0];
}, [cache, from]);
const stableOptions = useDeepMemo(() => ({ ...rest, from: ids }), [rest, ids]);
const observable = React.useMemo(() => client.watchFragment(stableOptions), [client, stableOptions]);
// Unfortunately we forgot to update the use case of `from: null` on
// useFragment in 4.0 to match `useSuspenseFragment`. As such, we need to
// fallback to data: {} with complete: false when `from` is `null` to maintain
// backwards compatibility. We should plan to change this in v5.
const getSnapshot = React.useCallback(() => (from === null ? nullResult : observable.getCurrentResult()), [from, observable]);
return useSyncExternalStore(React.useCallback((update) => {
let lastTimeout = 0;
const subscription = observable.subscribe({
next: () => {
// If we get another update before we've re-rendered, bail out of
// the update and try again. This ensures that the relative timing
// between useQuery and useFragment stays roughly the same as
// fixed in https://github.com/apollographql/apollo-client/pull/11083
clearTimeout(lastTimeout);
lastTimeout = setTimeout(update);
},
});
return () => {
subscription.unsubscribe();
clearTimeout(lastTimeout);
};
}, [observable]), getSnapshot, getSnapshot);
}
const nullResult = Object.freeze({
data: {},
dataState: "partial",
complete: false,
});
//# sourceMappingURL=useFragment.js.map