UNPKG

2.44 kBTypeScriptView Raw
1import * as React from "react"
2import { observer as observerLite, Observer } from "mobx-react-lite"
3
4import { makeClassComponentObserver } from "./observerClass"
5import { IReactComponent } from "./types/IReactComponent"
6
7const hasSymbol = typeof Symbol === "function" && Symbol.for
8
9// Using react-is had some issues (and operates on elements, not on types), see #608 / #609
10const ReactForwardRefSymbol = hasSymbol
11 ? Symbol.for("react.forward_ref")
12 : typeof React.forwardRef === "function" && React.forwardRef((props: any) => null)["$$typeof"]
13
14const ReactMemoSymbol = hasSymbol
15 ? Symbol.for("react.memo")
16 : typeof React.memo === "function" && React.memo((props: any) => null)["$$typeof"]
17
18/**
19 * Observer function / decorator
20 */
21export function observer<T extends IReactComponent>(component: T): T {
22 if (component["isMobxInjector"] === true) {
23 console.warn(
24 "Mobx observer: You are trying to use 'observer' on a component that already has 'inject'. Please apply 'observer' before applying 'inject'"
25 )
26 }
27
28 if (ReactMemoSymbol && component["$$typeof"] === ReactMemoSymbol) {
29 throw new Error(
30 "Mobx observer: You are trying to use 'observer' on a function component wrapped in either another observer or 'React.memo'. The observer already applies 'React.memo' for you."
31 )
32 }
33
34 // Unwrap forward refs into `<Observer>` component
35 // we need to unwrap the render, because it is the inner render that needs to be tracked,
36 // not the ForwardRef HoC
37 if (ReactForwardRefSymbol && component["$$typeof"] === ReactForwardRefSymbol) {
38 const baseRender = component["render"]
39 if (typeof baseRender !== "function")
40 throw new Error("render property of ForwardRef was not a function")
41 return React.forwardRef(function ObserverForwardRef() {
42 const args = arguments
43 return <Observer>{() => baseRender.apply(undefined, args)}</Observer>
44 }) as T
45 }
46
47 // Function component
48 if (
49 typeof component === "function" &&
50 (!component.prototype || !component.prototype.render) &&
51 !component["isReactClass"] &&
52 !Object.prototype.isPrototypeOf.call(React.Component, component)
53 ) {
54 return observerLite(component as React.StatelessComponent<any>) as T
55 }
56
57 return makeClassComponentObserver(component as React.ComponentClass<any, any>) as T
58}