react-relay
Version:
A framework for building GraphQL-driven React applications.
227 lines (226 loc) • 11.3 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var useFragment = require('./useFragment');
var useLoadMoreFunction = require('./useLoadMoreFunction');
var useRefetchableFragmentInternal = require('./useRefetchableFragmentInternal');
var useRelayEnvironment = require('./useRelayEnvironment');
var useStaticFragmentNodeWarning = require('./useStaticFragmentNodeWarning');
var invariant = require('invariant');
var _require = require('react'),
useCallback = _require.useCallback,
useDebugValue = _require.useDebugValue,
useEffect = _require.useEffect,
useLayoutEffect = _require.useLayoutEffect,
useMemo = _require.useMemo,
useRef = _require.useRef,
useState = _require.useState;
var _require2 = require('relay-runtime'),
getFragment = _require2.getFragment,
getFragmentIdentifier = _require2.getFragmentIdentifier,
getPaginationMetadata = _require2.getPaginationMetadata;
var _require3 = require('relay-runtime'),
ConnectionInterface = _require3.ConnectionInterface,
getSelector = _require3.getSelector,
getValueAtPath = _require3.getValueAtPath;
function usePrefetchableForwardPaginationFragment_EXPERIMENTAL(fragmentInput, parentFragmentRef, bufferSize, initialSize, prefetchingLoadMoreOptions) {
var _fragmentInput$metada, _fragmentInput$metada2;
var minimalFetchSize = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
var fragmentNode = getFragment(fragmentInput);
useStaticFragmentNodeWarning(fragmentNode, 'first argument of usePrefetchableForwardPaginationFragment_EXPERIMENTAL()');
var componentDisplayName = 'usePrefetchableForwardPaginationFragment_EXPERIMENTAL()';
var _getPaginationMetadat = getPaginationMetadata(fragmentNode, componentDisplayName),
connectionPathInFragmentData = _getPaginationMetadat.connectionPathInFragmentData,
paginationRequest = _getPaginationMetadat.paginationRequest,
paginationMetadata = _getPaginationMetadat.paginationMetadata;
var _useRefetchableFragme = useRefetchableFragmentInternal(fragmentNode, parentFragmentRef, componentDisplayName),
fragmentData = _useRefetchableFragme.fragmentData,
fragmentRef = _useRefetchableFragme.fragmentRef,
refetch = _useRefetchableFragme.refetch;
var fragmentIdentifier = getFragmentIdentifier(fragmentNode, fragmentRef);
var edgeKeys = useMemo(function () {
var connection = getValueAtPath(fragmentData, connectionPathInFragmentData);
if (connection == null) {
return null;
}
var _ConnectionInterface$ = ConnectionInterface.get(),
EDGES = _ConnectionInterface$.EDGES;
return connection[EDGES];
}, [connectionPathInFragmentData, fragmentData]);
var sourceSize = edgeKeys == null ? -1 : edgeKeys.length;
var _useState = useState(initialSize != null ? initialSize : sourceSize),
_numInUse = _useState[0],
setNumInUse = _useState[1];
var numInUse = _numInUse;
if (_numInUse === -1 && sourceSize !== -1) {
numInUse = initialSize != null ? initialSize : sourceSize;
setNumInUse(numInUse);
}
var environment = useRelayEnvironment();
var _useState2 = useState(false),
isLoadingMore = _useState2[0],
reallySetIsLoadingMore = _useState2[1];
var _useState3 = useState(false),
isRefetching = _useState3[0],
setIsRefetching = _useState3[1];
var availableSizeRef = useRef(0);
var setIsLoadingMore = useCallback(function (value) {
var _environment$getSched;
var schedule = (_environment$getSched = environment.getScheduler()) === null || _environment$getSched === void 0 ? void 0 : _environment$getSched.schedule;
if (schedule) {
schedule(function () {
reallySetIsLoadingMore(value);
});
} else {
reallySetIsLoadingMore(value);
}
}, [environment]);
var isLoadingMoreRef = useRef(false);
var observer = useMemo(function () {
return {
start: function start() {
isLoadingMoreRef.current = true;
reallySetIsLoadingMore(true);
},
complete: function complete() {
isLoadingMoreRef.current = false;
setIsLoadingMore(false);
},
error: function error() {
isLoadingMoreRef.current = false;
setIsLoadingMore(false);
}
};
}, [setIsLoadingMore]);
var handleReset = useCallback(function () {
if (!isRefetching) {
var _environment$getSched2;
var schedule = (_environment$getSched2 = environment.getScheduler()) === null || _environment$getSched2 === void 0 ? void 0 : _environment$getSched2.schedule;
if (schedule) {
schedule(function () {
setNumInUse(-1);
});
} else {
setNumInUse(-1);
}
}
isLoadingMoreRef.current = false;
setIsLoadingMore(false);
}, [environment, isRefetching, setIsLoadingMore]);
var _useLoadMoreFunction = useLoadMoreFunction({
componentDisplayName: componentDisplayName,
connectionPathInFragmentData: connectionPathInFragmentData,
direction: 'forward',
fragmentData: fragmentData,
fragmentIdentifier: fragmentIdentifier,
fragmentNode: fragmentNode,
fragmentRef: fragmentRef,
paginationMetadata: paginationMetadata,
paginationRequest: paginationRequest,
observer: observer,
onReset: handleReset
}),
loadMore = _useLoadMoreFunction[0],
hasNext = _useLoadMoreFunction[1],
disposeFetchNext = _useLoadMoreFunction[2];
useLayoutEffect(function () {
availableSizeRef.current = sourceSize - numInUse;
}, [numInUse, sourceSize]);
var prefetchingUNSTABLE_extraVariables = prefetchingLoadMoreOptions === null || prefetchingLoadMoreOptions === void 0 ? void 0 : prefetchingLoadMoreOptions.UNSTABLE_extraVariables;
var prefetchingOnComplete = prefetchingLoadMoreOptions === null || prefetchingLoadMoreOptions === void 0 ? void 0 : prefetchingLoadMoreOptions.onComplete;
var showMore = useCallback(function (numToAdd, options) {
if (!isLoadingMoreRef.current || availableSizeRef.current >= 0) {
availableSizeRef.current -= numToAdd;
setNumInUse(function (lastNumInUse) {
return lastNumInUse + numToAdd;
});
if (!isLoadingMoreRef.current && availableSizeRef.current < 0) {
loadMore(Math.max(minimalFetchSize, Math.min(numToAdd, bufferSize - availableSizeRef.current)), options !== null && options !== void 0 ? options : {
onComplete: prefetchingOnComplete,
UNSTABLE_extraVariables: typeof prefetchingUNSTABLE_extraVariables === 'function' ? prefetchingUNSTABLE_extraVariables({
hasNext: hasNext,
data: fragmentData,
getServerEdges: function getServerEdges() {
var selector = getSelector(edgesFragment, edgeKeys);
if (selector == null) {
return [];
}
!(selector.kind === 'PluralReaderSelector') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected a plural selector') : invariant(false) : void 0;
return selector.selectors.map(function (sel) {
return environment.lookup(sel).data;
});
}
}) : prefetchingUNSTABLE_extraVariables
});
}
}
}, [bufferSize, loadMore, minimalFetchSize, edgeKeys, fragmentData, prefetchingUNSTABLE_extraVariables, prefetchingOnComplete]);
var edgesFragment = (_fragmentInput$metada = fragmentInput.metadata) === null || _fragmentInput$metada === void 0 ? void 0 : (_fragmentInput$metada2 = _fragmentInput$metada.refetch) === null || _fragmentInput$metada2 === void 0 ? void 0 : _fragmentInput$metada2.edgesFragment;
!(edgesFragment != null) ? process.env.NODE_ENV !== "production" ? invariant(false, 'usePrefetchableForwardPaginationFragment_EXPERIMENTAL: Expected the edge fragment to be defined, ' + 'please make sure you have added `prefetchable_pagination: true` to `@connection`') : invariant(false) : void 0;
useEffect(function () {
if (!isLoadingMoreRef.current && !isLoadingMore && !isRefetching && hasNext && (sourceSize - numInUse < bufferSize || numInUse > sourceSize)) {
var onComplete = prefetchingOnComplete;
loadMore(Math.max(bufferSize - Math.max(sourceSize - numInUse, 0), numInUse - sourceSize, minimalFetchSize), {
onComplete: onComplete,
UNSTABLE_extraVariables: typeof prefetchingUNSTABLE_extraVariables === 'function' ? prefetchingUNSTABLE_extraVariables({
hasNext: hasNext,
data: fragmentData,
getServerEdges: function getServerEdges() {
var selector = getSelector(edgesFragment, edgeKeys);
if (selector == null) {
return [];
}
!(selector.kind === 'PluralReaderSelector') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Expected a plural selector') : invariant(false) : void 0;
return selector.selectors.map(function (sel) {
return environment.lookup(sel).data;
});
}
}) : prefetchingUNSTABLE_extraVariables
});
}
}, [hasNext, bufferSize, isRefetching, loadMore, numInUse, prefetchingUNSTABLE_extraVariables, prefetchingOnComplete, sourceSize, edgeKeys, isLoadingMore, minimalFetchSize, environment, edgesFragment]);
var realNumInUse = Math.min(numInUse, sourceSize);
var derivedEdgeKeys = useMemo(function () {
var _edgeKeys$slice;
return (_edgeKeys$slice = edgeKeys === null || edgeKeys === void 0 ? void 0 : edgeKeys.slice(0, realNumInUse)) !== null && _edgeKeys$slice !== void 0 ? _edgeKeys$slice : [];
}, [edgeKeys, realNumInUse]);
var edges = useFragment(edgesFragment, derivedEdgeKeys);
var refetchPagination = useCallback(function (variables, options) {
disposeFetchNext();
setIsRefetching(true);
return refetch(variables, (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, options), {}, {
onComplete: function onComplete(maybeError) {
var _environment$getSched3, _options$onComplete;
var schedule = (_environment$getSched3 = environment.getScheduler()) === null || _environment$getSched3 === void 0 ? void 0 : _environment$getSched3.schedule;
if (schedule) {
schedule(function () {
setIsRefetching(false);
setNumInUse(-1);
});
} else {
setIsRefetching(false);
setNumInUse(-1);
}
options === null || options === void 0 ? void 0 : (_options$onComplete = options.onComplete) === null || _options$onComplete === void 0 ? void 0 : _options$onComplete.call(options, maybeError);
},
__environment: undefined
}));
}, [disposeFetchNext, environment, refetch]);
if (process.env.NODE_ENV !== "production") {
useDebugValue({
fragment: fragmentNode.name,
data: fragmentData,
hasNext: hasNext,
isLoadingNext: isLoadingMore
});
}
return {
edges: edges,
data: fragmentData,
loadNext: showMore,
hasNext: hasNext || sourceSize > numInUse,
isLoadingNext: isLoadingMore && numInUse > sourceSize,
refetch: refetchPagination
};
}
module.exports = usePrefetchableForwardPaginationFragment_EXPERIMENTAL;