useUniqueMemo.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.default = void 0;
  7. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  8. var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
  9. var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
  10. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  11. var _react = _interopRequireDefault(require("react"));
  12. var BEAT_LIMIT = 1000 * 60 * 10;
  13. /**
  14. * A helper class to map keys to values.
  15. * It supports both primitive keys and object keys.
  16. */
  17. var ArrayKeyMap = /*#__PURE__*/function () {
  18. function ArrayKeyMap() {
  19. (0, _classCallCheck2.default)(this, ArrayKeyMap);
  20. (0, _defineProperty2.default)(this, "map", new Map());
  21. // Use WeakMap to avoid memory leak
  22. (0, _defineProperty2.default)(this, "objectIDMap", new WeakMap());
  23. (0, _defineProperty2.default)(this, "nextID", 0);
  24. (0, _defineProperty2.default)(this, "lastAccessBeat", new Map());
  25. // We will clean up the cache when reach the limit
  26. (0, _defineProperty2.default)(this, "accessBeat", 0);
  27. }
  28. (0, _createClass2.default)(ArrayKeyMap, [{
  29. key: "set",
  30. value: function set(keys, value) {
  31. // New set will trigger clear
  32. this.clear();
  33. // Set logic
  34. var compositeKey = this.getCompositeKey(keys);
  35. this.map.set(compositeKey, value);
  36. this.lastAccessBeat.set(compositeKey, Date.now());
  37. }
  38. }, {
  39. key: "get",
  40. value: function get(keys) {
  41. var compositeKey = this.getCompositeKey(keys);
  42. var cache = this.map.get(compositeKey);
  43. this.lastAccessBeat.set(compositeKey, Date.now());
  44. this.accessBeat += 1;
  45. return cache;
  46. }
  47. }, {
  48. key: "getCompositeKey",
  49. value: function getCompositeKey(keys) {
  50. var _this = this;
  51. var ids = keys.map(function (key) {
  52. if (key && (0, _typeof2.default)(key) === 'object') {
  53. return "obj_".concat(_this.getObjectID(key));
  54. }
  55. return "".concat((0, _typeof2.default)(key), "_").concat(key);
  56. });
  57. return ids.join('|');
  58. }
  59. }, {
  60. key: "getObjectID",
  61. value: function getObjectID(obj) {
  62. if (this.objectIDMap.has(obj)) {
  63. return this.objectIDMap.get(obj);
  64. }
  65. var id = this.nextID;
  66. this.objectIDMap.set(obj, id);
  67. this.nextID += 1;
  68. return id;
  69. }
  70. }, {
  71. key: "clear",
  72. value: function clear() {
  73. var _this2 = this;
  74. if (this.accessBeat > 10000) {
  75. var now = Date.now();
  76. this.lastAccessBeat.forEach(function (beat, key) {
  77. if (now - beat > BEAT_LIMIT) {
  78. _this2.map.delete(key);
  79. _this2.lastAccessBeat.delete(key);
  80. }
  81. });
  82. this.accessBeat = 0;
  83. }
  84. }
  85. }]);
  86. return ArrayKeyMap;
  87. }();
  88. var uniqueMap = new ArrayKeyMap();
  89. /**
  90. * Like `useMemo`, but this hook result will be shared across all instances.
  91. */
  92. function useUniqueMemo(memoFn, deps) {
  93. return _react.default.useMemo(function () {
  94. var cachedValue = uniqueMap.get(deps);
  95. if (cachedValue) {
  96. return cachedValue;
  97. }
  98. var newValue = memoFn();
  99. uniqueMap.set(deps, newValue);
  100. return newValue;
  101. }, deps);
  102. }
  103. var _default = exports.default = useUniqueMemo;