next-utils
Version:
Collection of handy utility functions for working within a Next.js project.
93 lines (73 loc) • 3.23 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports["default"] = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
function makeDefaultQueryInfo() {
return {
seen: false,
observable: null
};
}
var RenderPromises = /*#__PURE__*/function () {
function RenderPromises() {
(0, _defineProperty2["default"])(this, "renderPromises", new Map());
(0, _defineProperty2["default"])(this, "queryInfoTrie", new Map());
}
var _proto = RenderPromises.prototype;
// Registers the server side rendered observable.
_proto.registerSSRObservable = function registerSSRObservable(instance, observable) {
this.lookupQueryInfo(instance).observable = observable;
} // Get's the cached observable that matches the SSR Query instances query and variables.
;
_proto.getSSRObservable = function getSSRObservable(instance) {
return this.lookupQueryInfo(instance).observable;
};
_proto.addQueryPromise = function addQueryPromise(instance, finish) {
var info = this.lookupQueryInfo(instance);
if (!info.seen) {
this.renderPromises.set(instance, new Promise(function (resolve) {
resolve(instance.fetchData());
})); // Render null to abandon this subtree for this rendering, so that we
// can wait for the data to arrive.
return null;
}
return finish();
};
_proto.hasPromises = function hasPromises() {
return this.renderPromises.size > 0;
};
_proto.consumeAndAwaitPromises = function consumeAndAwaitPromises() {
var _this = this;
var promises = [];
this.renderPromises.forEach(function (promise, instance) {
// Make sure we never try to call fetchData for this query document and
// these variables again. Since the instance objects change with
// every rendering, deduplicating them by query and variables is the
// best we can do. If a different Query component happens to have the
// same query document and variables, it will be immediately rendered
// by calling finish() in addQueryPromise, which could result in the
// rendering of an unwanted loading state, but that's not nearly as bad
// as getting stuck in an infinite rendering loop because we kept calling
// instance.fetchData for the same Query component indefinitely.
_this.lookupQueryInfo(instance).seen = true;
promises.push(promise);
});
this.renderPromises.clear();
return Promise.all(promises);
};
_proto.lookupQueryInfo = function lookupQueryInfo(instance) {
var queryInfoTrie = this.queryInfoTrie;
var queryObject = instance.props;
var varMap = queryInfoTrie.get(JSON.stringify(queryObject)) || new Map();
if (!queryInfoTrie.has(JSON.stringify(queryObject))) {
queryInfoTrie.set(JSON.stringify(queryObject), varMap);
}
var variablesString = JSON.stringify(queryObject);
var info = varMap.get(variablesString) || makeDefaultQueryInfo();
if (!varMap.has(variablesString)) varMap.set(variablesString, info);
return info;
};
return RenderPromises;
}();
exports["default"] = RenderPromises;
;