import * as React from "react"; import { observer } from 'mobx-react'; import { decorator_compatibility } from './utils'; /** * Method decorator to make render methods MobX Observers. * Apply to a method that returns a React Element: * * ```jsx * @observerMethod * renderItem({ observable }) { * return
{observable.value}
* } * ``` */ export const observerMethod = decorator_compatibility({ legacy(target, key, descriptor?) { let fn = descriptor.value; if (typeof fn !== 'function') { throw new TypeError(`@observerMethod decorator can only be applied to methods not: ${typeof fn}`); } // In IE11 calling Object.defineProperty has a side-effect of evaluating the // getter for the property which is being replaced. This causes infinite // recursion and an "Out of stack space" error. let definingProperty = false; return { configurable: true, get() { // eslint-disable-next-line no-prototype-builtins if (definingProperty || this === target.prototype || this.hasOwnProperty(key) || typeof fn !== 'function') { return fn; } const boundFn = fn.bind(this); const ObserverComponent = observer(boundFn); ObserverComponent.displayName = `ObserverMethod(${fn.name})`; const wrappedFn = (props) => React.createElement(ObserverComponent, props); definingProperty = true; Object.defineProperty(this, key, { configurable: true, get() { return wrappedFn; }, set(value) { fn = value; delete this[key]; } }); definingProperty = false; return wrappedFn; }, set(value) { fn = value; } }; }, stage3(value, context) { if (context.kind != "method") throw new TypeError(`@observerMethod decorator can only be applied to methods not: ${context.kind}`); context.addInitializer(function () { const f = this[context.name]; const boundFn = f.bind(this); const ObserverComponent = observer(boundFn); ObserverComponent.displayName = `ObserverMethod(${context.name})`; const wrappedFn = (props) => React.createElement(ObserverComponent, props); this[context.name] = wrappedFn; }) }, }) /** * @deprecated */ export function observerMethod1(target, key, descriptor) { let fn = descriptor.value; if (typeof fn !== 'function') { throw new TypeError(`@observerMethod decorator can only be applied to methods not: ${typeof fn}`); } // In IE11 calling Object.defineProperty has a side-effect of evaluating the // getter for the property which is being replaced. This causes infinite // recursion and an "Out of stack space" error. let definingProperty = false; return { configurable: true, get() { // eslint-disable-next-line no-prototype-builtins if (definingProperty || this === target.prototype || this.hasOwnProperty(key) || typeof fn !== 'function') { return fn; } const boundFn = fn.bind(this); const ObserverComponent = observer(boundFn); ObserverComponent.displayName = `ObserverMethod(${fn.name})`; const wrappedFn = (props) => React.createElement(ObserverComponent, props); definingProperty = true; Object.defineProperty(this, key, { configurable: true, get() { return wrappedFn; }, set(value) { fn = value; delete this[key]; } }); definingProperty = false; return wrappedFn; }, set(value) { fn = value; } }; }