[RN] Remove isMounted() false positive warning (#13511)
Dan Abramov committed
Aug 30, 2018 at 18:42 UTC
b3d8c5376f1e0510963262d26e5029a9c463922f
5 files changed
+53
-31
packages/react-native-renderer/src/NativeMethodsMixin.js
+5
-5
@@ -22,7 +22,7 @@ import UIManager from 'UIManager';
22
23
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
24
import {
25
- mountSafeCallback,
25
+ mountSafeCallback_NOT_REALLY_SAFE,
26
throwOnStylesProp,
27
warnForStyleProps,
28
} from './NativeMethodsMixinUtils';
@@ -67,7 +67,7 @@ export default function(
67
measure: function(callback: MeasureOnSuccessCallback) {
68
UIManager.measure(
69
findNodeHandle(this),
70
- mountSafeCallback(this, callback),
70
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
71
);
72
},
73
@@ -89,7 +89,7 @@ export default function(
89
measureInWindow: function(callback: MeasureInWindowOnSuccessCallback) {
90
UIManager.measureInWindow(
91
findNodeHandle(this),
92
- mountSafeCallback(this, callback),
92
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
93
);
94
},
95
@@ -109,8 +109,8 @@ export default function(
109
UIManager.measureLayout(
110
findNodeHandle(this),
111
relativeToNativeNode,
112
- mountSafeCallback(this, onFail),
113
- mountSafeCallback(this, onSuccess),
112
+ mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
113
+ mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
114
);
115
},
116
packages/react-native-renderer/src/NativeMethodsMixinUtils.js
+21
-11
@@ -11,26 +11,36 @@
11
* In the future, we should cleanup callbacks by cancelling them instead of
12
* using this.
13
*/
14
-export function mountSafeCallback(context: any, callback: ?Function): any {
14
+export function mountSafeCallback_NOT_REALLY_SAFE(
15
+ context: any,
16
+ callback: ?Function,
17
+): any {
18
return function() {
19
if (!callback) {
20
return undefined;
21
}
22
+ // This protects against createClass() components.
23
+ // We don't know if there is code depending on it.
24
+ // We intentionally don't use isMounted() because even accessing
25
+ // isMounted property on a React ES6 class will trigger a warning.
26
if (typeof context.__isMounted === 'boolean') {
20
- // TODO(gaearon): this is gross and should be removed.
21
- // It is currently necessary because View uses createClass,
22
- // and so any measure() calls on View (which are done by React
23
- // DevTools) trigger the isMounted() deprecation warning.
27
if (!context.__isMounted) {
28
return undefined;
29
}
27
- // The else branch is important so that we don't
28
- // trigger the deprecation warning by calling isMounted.
29
- } else if (typeof context.isMounted === 'function') {
30
- if (!context.isMounted()) {
31
- return undefined;
32
- }
30
}
31
+
32
+ // FIXME: there used to be other branches that protected
33
+ // against unmounted host components. But RN host components don't
34
+ // define isMounted() anymore, so those checks didn't do anything.
35
+
36
+ // They caused false positive warning noise so we removed them:
37
+ // https://github.com/facebook/react-native/issues/18868#issuecomment-413579095
38
+
39
+ // However, this means that the callback is NOT guaranteed to be safe
40
+ // for host components. The solution we should implement is to make
41
+ // UIManager.measure() and similar calls truly cancelable. Then we
42
+ // can change our own code calling them to cancel when something unmounts.
43
+
44
return callback.apply(context, arguments);
45
};
46
}
packages/react-native-renderer/src/ReactFabricHostConfig.js
+11
-5
@@ -15,7 +15,10 @@ import type {
15
ReactNativeBaseComponentViewConfig,
16
} from './ReactNativeTypes';
17
18
-import {mountSafeCallback, warnForStyleProps} from './NativeMethodsMixinUtils';
18
+import {
19
+ mountSafeCallback_NOT_REALLY_SAFE,
20
+ warnForStyleProps,
21
+} from './NativeMethodsMixinUtils';
22
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
23
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
24
import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
@@ -104,13 +107,16 @@ class ReactFabricHostComponent {
107
}
108
109
measure(callback: MeasureOnSuccessCallback) {
107
- UIManager.measure(this._nativeTag, mountSafeCallback(this, callback));
110
+ UIManager.measure(
111
+ this._nativeTag,
112
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
113
+ );
114
}
115
116
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
117
UIManager.measureInWindow(
118
this._nativeTag,
113
- mountSafeCallback(this, callback),
119
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
120
);
121
}
122
@@ -122,8 +128,8 @@ class ReactFabricHostComponent {
128
UIManager.measureLayout(
129
this._nativeTag,
130
relativeToNativeNode,
125
- mountSafeCallback(this, onFail),
126
- mountSafeCallback(this, onSuccess),
131
+ mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
132
+ mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
133
);
134
}
135
packages/react-native-renderer/src/ReactNativeComponent.js
+5
-5
@@ -22,7 +22,7 @@ import TextInputState from 'TextInputState';
22
import UIManager from 'UIManager';
23
24
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
25
-import {mountSafeCallback} from './NativeMethodsMixinUtils';
25
+import {mountSafeCallback_NOT_REALLY_SAFE} from './NativeMethodsMixinUtils';
26
27
export default function(
28
findNodeHandle: any => ?number,
@@ -82,7 +82,7 @@ export default function(
82
measure(callback: MeasureOnSuccessCallback): void {
83
UIManager.measure(
84
findNodeHandle(this),
85
- mountSafeCallback(this, callback),
85
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
86
);
87
}
88
@@ -102,7 +102,7 @@ export default function(
102
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void {
103
UIManager.measureInWindow(
104
findNodeHandle(this),
105
- mountSafeCallback(this, callback),
105
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
106
);
107
}
108
@@ -120,8 +120,8 @@ export default function(
120
UIManager.measureLayout(
121
findNodeHandle(this),
122
relativeToNativeNode,
123
- mountSafeCallback(this, onFail),
124
- mountSafeCallback(this, onSuccess),
123
+ mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
124
+ mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
125
);
126
}
127
packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
+11
-5
@@ -21,7 +21,10 @@ import TextInputState from 'TextInputState';
21
import UIManager from 'UIManager';
22
23
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
24
-import {mountSafeCallback, warnForStyleProps} from './NativeMethodsMixinUtils';
24
+import {
25
+ mountSafeCallback_NOT_REALLY_SAFE,
26
+ warnForStyleProps,
27
+} from './NativeMethodsMixinUtils';
28
29
/**
30
* This component defines the same methods as NativeMethodsMixin but without the
@@ -50,13 +53,16 @@ class ReactNativeFiberHostComponent {
53
}
54
55
measure(callback: MeasureOnSuccessCallback) {
53
- UIManager.measure(this._nativeTag, mountSafeCallback(this, callback));
56
+ UIManager.measure(
57
+ this._nativeTag,
58
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
59
+ );
60
}
61
62
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
63
UIManager.measureInWindow(
64
this._nativeTag,
59
- mountSafeCallback(this, callback),
65
+ mountSafeCallback_NOT_REALLY_SAFE(this, callback),
66
);
67
}
68
@@ -68,8 +74,8 @@ class ReactNativeFiberHostComponent {
74
UIManager.measureLayout(
75
this._nativeTag,
76
relativeToNativeNode,
71
- mountSafeCallback(this, onFail),
72
- mountSafeCallback(this, onSuccess),
77
+ mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
78
+ mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
79
);
80
}
81