graphql-react
Version:
A GraphQL client for React using modern context and hooks APIs that’s lightweight (< 4 kB) but powerful; the first Relay and Apollo alternative with server side rendering.
72 lines (63 loc) • 2.2 kB
JavaScript
import React from "react";
import LoadingCacheValue from "./LoadingCacheValue.mjs";
import fetchGraphQL from "./fetchGraphQL.mjs";
import useCache from "./useCache.mjs";
import useLoading from "./useLoading.mjs";
/**
* A React hook to get a function for loading a GraphQL operation.
* @kind function
* @name useLoadGraphQL
* @returns {LoadGraphQL} Loads a GraphQL operation.
* @example <caption>How to import.</caption>
* ```js
* import useLoadGraphQL from "graphql-react/useLoadGraphQL.mjs";
* ```
*/
export default function useLoadGraphQL() {
const cache = useCache();
const loading = useLoading();
return React.useCallback(
(cacheKey, fetchUri, fetchOptions) => {
if (typeof cacheKey !== "string")
throw new TypeError("Argument 1 `cacheKey` must be a string.");
if (typeof fetchUri !== "string")
throw new TypeError("Argument 2 `fetchUri` must be a string.");
if (
typeof fetchOptions !== "object" ||
!fetchOptions ||
Array.isArray(fetchOptions)
)
throw new TypeError("Argument 3 `fetchOptions` must be an object.");
// Avoid mutating the input fetch options.
const { signal, ...modifiedFetchOptions } = fetchOptions;
const abortController = new AbortController();
// Respect an existing abort controller signal.
if (signal)
signal.aborted
? // Signal already aborted, so immediately abort.
abortController.abort()
: // Signal not already aborted, so setup a listener to abort when it
// does.
signal.addEventListener(
"abort",
() => {
abortController.abort();
},
{
// Prevent a memory leak if the existing abort controller is
// long lasting, or controls multiple things.
once: true,
}
);
modifiedFetchOptions.signal = abortController.signal;
return new LoadingCacheValue(
loading,
cache,
cacheKey,
fetchGraphQL(fetchUri, modifiedFetchOptions),
abortController
);
},
[cache, loading]
);
}