react-relay
Version:
A framework for building GraphQL-driven React applications.
130 lines (129 loc) • 6.96 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var getConnectionState = require('./getConnectionState');
var useIsMountedRef = require('./useIsMountedRef');
var useIsOperationNodeActive = require('./useIsOperationNodeActive');
var useRelayEnvironment = require('./useRelayEnvironment');
var invariant = require('invariant');
var _require = require('react'),
useCallback = _require.useCallback,
useRef = _require.useRef,
useState = _require.useState;
var _require2 = require('relay-runtime'),
fetchQuery = _require2.__internal.fetchQuery,
createOperationDescriptor = _require2.createOperationDescriptor,
getPaginationVariables = _require2.getPaginationVariables,
getRefetchMetadata = _require2.getRefetchMetadata,
getSelector = _require2.getSelector;
var warning = require("fbjs/lib/warning");
function useLoadMoreFunction_EXPERIMENTAL(args) {
var direction = args.direction,
fragmentNode = args.fragmentNode,
fragmentRef = args.fragmentRef,
fragmentIdentifier = args.fragmentIdentifier,
fragmentData = args.fragmentData,
connectionPathInFragmentData = args.connectionPathInFragmentData,
paginationRequest = args.paginationRequest,
paginationMetadata = args.paginationMetadata,
componentDisplayName = args.componentDisplayName,
observer = args.observer,
onReset = args.onReset;
var environment = useRelayEnvironment();
var _getRefetchMetadata = getRefetchMetadata(fragmentNode, componentDisplayName),
identifierInfo = _getRefetchMetadata.identifierInfo;
var identifierValue = (identifierInfo === null || identifierInfo === void 0 ? void 0 : identifierInfo.identifierField) != null && fragmentData != null && typeof fragmentData === 'object' ? fragmentData[identifierInfo.identifierField] : null;
var fetchStatusRef = useRef({
kind: 'none'
});
var _useState = useState(environment),
mirroredEnvironment = _useState[0],
setMirroredEnvironment = _useState[1];
var _useState2 = useState(fragmentIdentifier),
mirroredFragmentIdentifier = _useState2[0],
setMirroredFragmentIdentifier = _useState2[1];
var isParentQueryActive = useIsOperationNodeActive(fragmentNode, fragmentRef);
var forceDisposeFn = useCallback(function () {
if (fetchStatusRef.current.kind === 'fetching') {
fetchStatusRef.current.subscription.unsubscribe();
}
fetchStatusRef.current = {
kind: 'none'
};
}, []);
var shouldReset = environment !== mirroredEnvironment || fragmentIdentifier !== mirroredFragmentIdentifier;
if (shouldReset) {
forceDisposeFn();
onReset();
setMirroredEnvironment(environment);
setMirroredFragmentIdentifier(fragmentIdentifier);
}
var _getConnectionState = getConnectionState(direction, fragmentNode, fragmentData, connectionPathInFragmentData),
cursor = _getConnectionState.cursor,
hasMore = _getConnectionState.hasMore;
var isMountedRef = useIsMountedRef();
var loadMore = useCallback(function (count, options) {
var onComplete = options === null || options === void 0 ? void 0 : options.onComplete;
if (isMountedRef.current !== true) {
process.env.NODE_ENV !== "production" ? warning(false, 'Relay: Unexpected fetch on unmounted component for fragment ' + '`%s` in `%s`. It looks like some instances of your component are ' + 'still trying to fetch data but they already unmounted. ' + 'Please make sure you clear all timers, intervals, ' + 'async calls, etc that may trigger a fetch.', fragmentNode.name, componentDisplayName) : void 0;
return {
dispose: function dispose() {}
};
}
var fragmentSelector = getSelector(fragmentNode, fragmentRef);
if (fetchStatusRef.current.kind === 'fetching' || fragmentData == null || isParentQueryActive) {
if (fragmentSelector == null) {
process.env.NODE_ENV !== "production" ? warning(false, 'Relay: Unexpected fetch while using a null fragment ref ' + 'for fragment `%s` in `%s`. When fetching more items, we expect ' + "initial fragment data to be non-null. Please make sure you're " + 'passing a valid fragment ref to `%s` before paginating.', fragmentNode.name, componentDisplayName, componentDisplayName) : void 0;
}
if (onComplete) {
onComplete(null);
}
return {
dispose: function dispose() {}
};
}
!(fragmentSelector != null && fragmentSelector.kind !== 'PluralReaderSelector') ? process.env.NODE_ENV !== "production" ? invariant(false, 'Relay: Expected to be able to find a non-plural fragment owner for ' + "fragment `%s` when using `%s`. If you're seeing this, " + 'this is likely a bug in Relay.', fragmentNode.name, componentDisplayName) : invariant(false) : void 0;
var parentVariables = fragmentSelector.owner.variables;
var fragmentVariables = fragmentSelector.variables;
var extraVariables = options === null || options === void 0 ? void 0 : options.UNSTABLE_extraVariables;
var baseVariables = (0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, parentVariables), fragmentVariables);
var paginationVariables = getPaginationVariables(direction, count, cursor, baseVariables, (0, _objectSpread2["default"])({}, extraVariables), paginationMetadata);
if (identifierInfo != null) {
if (typeof identifierValue !== 'string') {
process.env.NODE_ENV !== "production" ? warning(false, 'Relay: Expected result to have a string ' + '`%s` in order to refetch, got `%s`.', identifierInfo.identifierField, identifierValue) : void 0;
}
paginationVariables[identifierInfo.identifierQueryVariableName] = identifierValue;
}
var paginationQuery = createOperationDescriptor(paginationRequest, paginationVariables, {
force: true
});
fetchQuery(environment, paginationQuery).subscribe((0, _objectSpread2["default"])((0, _objectSpread2["default"])({}, observer), {}, {
start: function start(subscription) {
fetchStatusRef.current = {
kind: 'fetching',
subscription: subscription
};
observer.start && observer.start(subscription);
},
complete: function complete() {
fetchStatusRef.current = {
kind: 'none'
};
observer.complete && observer.complete();
onComplete && onComplete(null);
},
error: function error(_error) {
fetchStatusRef.current = {
kind: 'none'
};
observer.complete && observer.complete();
onComplete && onComplete(_error);
}
}));
return {
dispose: function dispose() {}
};
}, [environment, identifierValue, direction, cursor, isParentQueryActive, fragmentData, fragmentNode.name, fragmentRef, componentDisplayName]);
return [loadMore, hasMore, forceDisposeFn];
}
module.exports = useLoadMoreFunction_EXPERIMENTAL;