custom.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('mobx'), require('react')) :
  3. typeof define === 'function' && define.amd ? define(['exports', 'mobx', 'react'], factory) :
  4. (global = global || self, factory(global.mobxReactLite = {}, global.mobx, global.React));
  5. }(this, function (exports, mobx, React) { 'use strict';
  6. var React__default = 'default' in React ? React['default'] : React;
  7. if (!React.useState) {
  8. throw new Error("mobx-react-lite requires React with Hooks support");
  9. }
  10. if (!mobx.spy) {
  11. throw new Error("mobx-react-lite requires mobx at least version 4 to be available");
  12. }
  13. function useObservable(initialValue) {
  14. var observableRef = React.useRef(null);
  15. if (!observableRef.current) {
  16. observableRef.current = mobx.observable(initialValue);
  17. }
  18. return observableRef.current;
  19. }
  20. function useComputed(func, inputs) {
  21. if (inputs === void 0) { inputs = []; }
  22. var computed = React.useMemo(function () { return mobx.computed(func); }, inputs);
  23. return computed.get();
  24. }
  25. var doNothingDisposer = function () {
  26. // empty
  27. };
  28. /**
  29. * Adds an observable effect (reaction, autorun, or anything else that returns a disposer) that will be registered upon component creation and disposed upon unmounting.
  30. * Returns the generated disposer for early disposal.
  31. *
  32. * @export
  33. * @template D
  34. * @param {() => D} disposerGenerator A function that returns the disposer of the wanted effect.
  35. * @param {ReadonlyArray<any>} [inputs=[]] If you want the effect to be automatically re-created when some variable(s) are changed then pass them in this array.
  36. * @returns {D}
  37. */
  38. function useDisposable(disposerGenerator, inputs) {
  39. if (inputs === void 0) { inputs = []; }
  40. var disposerRef = React.useRef(null);
  41. var earlyDisposedRef = React.useRef(false);
  42. React.useEffect(function () {
  43. return lazyCreateDisposer(false);
  44. }, inputs);
  45. function lazyCreateDisposer(earlyDisposal) {
  46. // ensure that we won't create a new disposer if it was early disposed
  47. if (earlyDisposedRef.current) {
  48. return doNothingDisposer;
  49. }
  50. if (!disposerRef.current) {
  51. var newDisposer = disposerGenerator();
  52. if (typeof newDisposer !== "function") {
  53. var error = new Error("generated disposer must be a function");
  54. {
  55. // tslint:disable-next-line:no-console
  56. console.error(error);
  57. return doNothingDisposer;
  58. }
  59. }
  60. disposerRef.current = newDisposer;
  61. }
  62. return function () {
  63. if (disposerRef.current) {
  64. disposerRef.current();
  65. disposerRef.current = null;
  66. }
  67. if (earlyDisposal) {
  68. earlyDisposedRef.current = true;
  69. }
  70. };
  71. }
  72. return lazyCreateDisposer(true);
  73. }
  74. var globalIsUsingStaticRendering = false;
  75. function useStaticRendering(enable) {
  76. globalIsUsingStaticRendering = enable;
  77. }
  78. function isUsingStaticRendering() {
  79. return globalIsUsingStaticRendering;
  80. }
  81. /*! *****************************************************************************
  82. Copyright (c) Microsoft Corporation. All rights reserved.
  83. Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  84. this file except in compliance with the License. You may obtain a copy of the
  85. License at http://www.apache.org/licenses/LICENSE-2.0
  86. THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  87. KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  88. WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  89. MERCHANTABLITY OR NON-INFRINGEMENT.
  90. See the Apache Version 2.0 License for specific language governing permissions
  91. and limitations under the License.
  92. ***************************************************************************** */
  93. var __assign = function() {
  94. __assign = Object.assign || function __assign(t) {
  95. for (var s, i = 1, n = arguments.length; i < n; i++) {
  96. s = arguments[i];
  97. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
  98. }
  99. return t;
  100. };
  101. return __assign.apply(this, arguments);
  102. };
  103. function __read(o, n) {
  104. var m = typeof Symbol === "function" && o[Symbol.iterator];
  105. if (!m) return o;
  106. var i = m.call(o), r, ar = [], e;
  107. try {
  108. while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
  109. }
  110. catch (error) { e = { error: error }; }
  111. finally {
  112. try {
  113. if (r && !r.done && (m = i["return"])) m.call(i);
  114. }
  115. finally { if (e) throw e.error; }
  116. }
  117. return ar;
  118. }
  119. function printDebugValue(v) {
  120. if (!v.current) {
  121. return "<unknown>";
  122. }
  123. return mobx.getDependencyTree(v.current);
  124. }
  125. var EMPTY_ARRAY = [];
  126. function useUnmount(fn) {
  127. React.useEffect(function () { return fn; }, EMPTY_ARRAY);
  128. }
  129. function useForceUpdate() {
  130. var _a = __read(React.useState(0), 2), setTick = _a[1];
  131. var update = React.useCallback(function () {
  132. setTick(function (tick) { return tick + 1; });
  133. }, []);
  134. return update;
  135. }
  136. function isPlainObject(value) {
  137. if (!value || typeof value !== "object") {
  138. return false;
  139. }
  140. var proto = Object.getPrototypeOf(value);
  141. return !proto || proto === Object.prototype;
  142. }
  143. var EMPTY_OBJECT = {};
  144. function useObserver(fn, baseComponentName, options) {
  145. if (baseComponentName === void 0) { baseComponentName = "observed"; }
  146. if (options === void 0) { options = EMPTY_OBJECT; }
  147. if (isUsingStaticRendering()) {
  148. return fn();
  149. }
  150. var wantedForceUpdateHook = options.useForceUpdate || useForceUpdate;
  151. var forceUpdate = wantedForceUpdateHook();
  152. var reaction = React.useRef(null);
  153. if (!reaction.current) {
  154. reaction.current = new mobx.Reaction("observer(" + baseComponentName + ")", function () {
  155. forceUpdate();
  156. });
  157. }
  158. var dispose = function () {
  159. if (reaction.current && !reaction.current.isDisposed) {
  160. reaction.current.dispose();
  161. reaction.current = null;
  162. }
  163. };
  164. React.useDebugValue(reaction, printDebugValue);
  165. useUnmount(function () {
  166. dispose();
  167. });
  168. // render the original component, but have the
  169. // reaction track the observables, so that rendering
  170. // can be invalidated (see above) once a dependency changes
  171. var rendering;
  172. var exception;
  173. reaction.current.track(function () {
  174. try {
  175. rendering = fn();
  176. }
  177. catch (e) {
  178. exception = e;
  179. }
  180. });
  181. if (exception) {
  182. dispose();
  183. throw exception; // re-throw any exceptions catched during rendering
  184. }
  185. return rendering;
  186. }
  187. // n.b. base case is not used for actual typings or exported in the typing files
  188. function observer(baseComponent, options) {
  189. // The working of observer is explained step by step in this talk: https://www.youtube.com/watch?v=cPF4iBedoF0&feature=youtu.be&t=1307
  190. if (isUsingStaticRendering()) {
  191. return baseComponent;
  192. }
  193. var realOptions = __assign({ forwardRef: false }, options);
  194. var baseComponentName = baseComponent.displayName || baseComponent.name;
  195. var wrappedComponent = function (props, ref) {
  196. return useObserver(function () { return baseComponent(props, ref); }, baseComponentName);
  197. };
  198. wrappedComponent.displayName = baseComponentName;
  199. // memo; we are not intested in deep updates
  200. // in props; we assume that if deep objects are changed,
  201. // this is in observables, which would have been tracked anyway
  202. var memoComponent;
  203. if (realOptions.forwardRef) {
  204. // we have to use forwardRef here because:
  205. // 1. it cannot go before memo, only after it
  206. // 2. forwardRef converts the function into an actual component, so we can't let the baseComponent do it
  207. // since it wouldn't be a callable function anymore
  208. memoComponent = React.memo(React.forwardRef(wrappedComponent));
  209. }
  210. else {
  211. memoComponent = React.memo(wrappedComponent);
  212. }
  213. copyStaticProperties(baseComponent, memoComponent);
  214. memoComponent.displayName = baseComponentName;
  215. return memoComponent;
  216. }
  217. // based on https://github.com/mridgway/hoist-non-react-statics/blob/master/src/index.js
  218. var hoistBlackList = {
  219. $$typeof: true,
  220. render: true,
  221. compare: true,
  222. type: true
  223. };
  224. function copyStaticProperties(base, target) {
  225. Object.keys(base).forEach(function (key) {
  226. if (base.hasOwnProperty(key) && !hoistBlackList[key]) {
  227. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(base, key));
  228. }
  229. });
  230. }
  231. function ObserverComponent(_a) {
  232. var children = _a.children, render = _a.render;
  233. var component = children || render;
  234. if (typeof component !== "function") {
  235. return null;
  236. }
  237. return useObserver(component);
  238. }
  239. ObserverComponent.propTypes = {
  240. children: ObserverPropsCheck,
  241. render: ObserverPropsCheck
  242. };
  243. ObserverComponent.displayName = "Observer";
  244. function ObserverPropsCheck(props, key, componentName, location, propFullName) {
  245. var extraKey = key === "children" ? "render" : "children";
  246. var hasProp = typeof props[key] === "function";
  247. var hasExtraProp = typeof props[extraKey] === "function";
  248. if (hasProp && hasExtraProp) {
  249. return new Error("MobX Observer: Do not use children and render in the same time in`" + componentName);
  250. }
  251. if (hasProp || hasExtraProp) {
  252. return null;
  253. }
  254. return new Error("Invalid prop `" +
  255. propFullName +
  256. "` of type `" +
  257. typeof props[key] +
  258. "` supplied to" +
  259. " `" +
  260. componentName +
  261. "`, expected `function`.");
  262. }
  263. function useAsObservableSourceInternal(current, usedByLocalStore) {
  264. if (usedByLocalStore && current === undefined) {
  265. return undefined;
  266. }
  267. var _a = __read(React__default.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0];
  268. mobx.runInAction(function () {
  269. Object.assign(res, current);
  270. });
  271. return res;
  272. }
  273. function useAsObservableSource(current) {
  274. return useAsObservableSourceInternal(current, false);
  275. }
  276. function useLocalStore(initializer, current) {
  277. var source = useAsObservableSourceInternal(current, true);
  278. return React__default.useState(function () {
  279. var local = mobx.observable(initializer(source));
  280. if (isPlainObject(local)) {
  281. mobx.runInAction(function () {
  282. Object.keys(local).forEach(function (key) {
  283. var value = local[key];
  284. if (typeof value === "function") {
  285. // @ts-ignore No idea why ts2536 is popping out here
  286. local[key] = wrapInTransaction(value, local);
  287. }
  288. });
  289. });
  290. }
  291. return local;
  292. })[0];
  293. }
  294. // tslint:disable-next-line: ban-types
  295. function wrapInTransaction(fn, context) {
  296. return function () {
  297. var args = [];
  298. for (var _i = 0; _i < arguments.length; _i++) {
  299. args[_i] = arguments[_i];
  300. }
  301. return mobx.transaction(function () { return fn.apply(context, args); });
  302. };
  303. }
  304. var optimizeScheduler = function (reactionScheduler) {
  305. if (typeof reactionScheduler === "function") {
  306. mobx.configure({ reactionScheduler: reactionScheduler });
  307. }
  308. };
  309. exports.Observer = ObserverComponent;
  310. exports.isUsingStaticRendering = isUsingStaticRendering;
  311. exports.observer = observer;
  312. exports.optimizeScheduler = optimizeScheduler;
  313. exports.useAsObservableSource = useAsObservableSource;
  314. exports.useComputed = useComputed;
  315. exports.useDisposable = useDisposable;
  316. exports.useForceUpdate = useForceUpdate;
  317. exports.useLocalStore = useLocalStore;
  318. exports.useObservable = useObservable;
  319. exports.useObserver = useObserver;
  320. exports.useStaticRendering = useStaticRendering;
  321. Object.defineProperty(exports, '__esModule', { value: true });
  322. }));