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