useUniqueMemo.js 2.9 KB

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