use-sync-external-store-with-selector.development.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /**
  2. * @license React
  3. * use-sync-external-store-with-selector.development.js
  4. *
  5. * Copyright (c) Facebook, Inc. and its affiliates.
  6. *
  7. * This source code is licensed under the MIT license found in the
  8. * LICENSE file in the root directory of this source tree.
  9. */
  10. 'use strict';
  11. if (process.env.NODE_ENV !== "production") {
  12. (function() {
  13. 'use strict';
  14. /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
  15. if (
  16. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
  17. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===
  18. 'function'
  19. ) {
  20. __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
  21. }
  22. var React = require('react');
  23. /**
  24. * inlined Object.is polyfill to avoid requiring consumers ship their own
  25. * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
  26. */
  27. function is(x, y) {
  28. return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
  29. ;
  30. }
  31. var objectIs = typeof Object.is === 'function' ? Object.is : is;
  32. var useSyncExternalStore = React.useSyncExternalStore;
  33. // for CommonJS interop.
  34. var useRef = React.useRef,
  35. useEffect = React.useEffect,
  36. useMemo = React.useMemo,
  37. useDebugValue = React.useDebugValue; // Same as useSyncExternalStore, but supports selector and isEqual arguments.
  38. function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
  39. // Use this to track the rendered snapshot.
  40. var instRef = useRef(null);
  41. var inst;
  42. if (instRef.current === null) {
  43. inst = {
  44. hasValue: false,
  45. value: null
  46. };
  47. instRef.current = inst;
  48. } else {
  49. inst = instRef.current;
  50. }
  51. var _useMemo = useMemo(function () {
  52. // Track the memoized state using closure variables that are local to this
  53. // memoized instance of a getSnapshot function. Intentionally not using a
  54. // useRef hook, because that state would be shared across all concurrent
  55. // copies of the hook/component.
  56. var hasMemo = false;
  57. var memoizedSnapshot;
  58. var memoizedSelection;
  59. var memoizedSelector = function (nextSnapshot) {
  60. if (!hasMemo) {
  61. // The first time the hook is called, there is no memoized result.
  62. hasMemo = true;
  63. memoizedSnapshot = nextSnapshot;
  64. var _nextSelection = selector(nextSnapshot);
  65. if (isEqual !== undefined) {
  66. // Even if the selector has changed, the currently rendered selection
  67. // may be equal to the new selection. We should attempt to reuse the
  68. // current value if possible, to preserve downstream memoizations.
  69. if (inst.hasValue) {
  70. var currentSelection = inst.value;
  71. if (isEqual(currentSelection, _nextSelection)) {
  72. memoizedSelection = currentSelection;
  73. return currentSelection;
  74. }
  75. }
  76. }
  77. memoizedSelection = _nextSelection;
  78. return _nextSelection;
  79. } // We may be able to reuse the previous invocation's result.
  80. // We may be able to reuse the previous invocation's result.
  81. var prevSnapshot = memoizedSnapshot;
  82. var prevSelection = memoizedSelection;
  83. if (objectIs(prevSnapshot, nextSnapshot)) {
  84. // The snapshot is the same as last time. Reuse the previous selection.
  85. return prevSelection;
  86. } // The snapshot has changed, so we need to compute a new selection.
  87. // The snapshot has changed, so we need to compute a new selection.
  88. var nextSelection = selector(nextSnapshot); // If a custom isEqual function is provided, use that to check if the data
  89. // has changed. If it hasn't, return the previous selection. That signals
  90. // to React that the selections are conceptually equal, and we can bail
  91. // out of rendering.
  92. // If a custom isEqual function is provided, use that to check if the data
  93. // has changed. If it hasn't, return the previous selection. That signals
  94. // to React that the selections are conceptually equal, and we can bail
  95. // out of rendering.
  96. if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
  97. return prevSelection;
  98. }
  99. memoizedSnapshot = nextSnapshot;
  100. memoizedSelection = nextSelection;
  101. return nextSelection;
  102. }; // Assigning this to a constant so that Flow knows it can't change.
  103. // Assigning this to a constant so that Flow knows it can't change.
  104. var maybeGetServerSnapshot = getServerSnapshot === undefined ? null : getServerSnapshot;
  105. var getSnapshotWithSelector = function () {
  106. return memoizedSelector(getSnapshot());
  107. };
  108. var getServerSnapshotWithSelector = maybeGetServerSnapshot === null ? undefined : function () {
  109. return memoizedSelector(maybeGetServerSnapshot());
  110. };
  111. return [getSnapshotWithSelector, getServerSnapshotWithSelector];
  112. }, [getSnapshot, getServerSnapshot, selector, isEqual]),
  113. getSelection = _useMemo[0],
  114. getServerSelection = _useMemo[1];
  115. var value = useSyncExternalStore(subscribe, getSelection, getServerSelection);
  116. useEffect(function () {
  117. inst.hasValue = true;
  118. inst.value = value;
  119. }, [value]);
  120. useDebugValue(value);
  121. return value;
  122. }
  123. exports.useSyncExternalStoreWithSelector = useSyncExternalStoreWithSelector;
  124. /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
  125. if (
  126. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
  127. typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===
  128. 'function'
  129. ) {
  130. __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());
  131. }
  132. })();
  133. }