Upsell React DevTools in 16 (#10351)
* Upsell React DevTools * Fix Flow * Upsell message nits * Avoid extra checks in onCommitRoot and onCommitUnmount
Dan Abramov committed
Aug 2, 2017 at 18:56 UTC
982380863272b900e0500631b829408b96220aae
3 files changed
+96
-56
src/renderers/dom/fiber/ReactDOMFiberEntry.js
+34
-8
@@ -15,6 +15,7 @@
15
import type {Fiber} from 'ReactFiber';
16
import type {ReactNodeList} from 'ReactTypes';
17
18
+var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
19
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
20
var ReactControlledComponent = require('ReactControlledComponent');
21
var ReactDOMComponentTree = require('ReactDOMComponentTree');
@@ -804,14 +805,39 @@ var ReactDOMFiber = {
805
},
806
};
807
807
-if (typeof injectInternals === 'function') {
808
- injectInternals({
809
- findFiberByHostInstance: ReactDOMComponentTree.getClosestInstanceFromNode,
810
- findHostInstanceByFiber: DOMRenderer.findHostInstance,
811
- // This is an enum because we may add more (e.g. profiler build)
812
- bundleType: __DEV__ ? 1 : 0,
813
- version: ReactVersion,
814
- });
808
+const foundDevTools = injectInternals({
809
+ findFiberByHostInstance: ReactDOMComponentTree.getClosestInstanceFromNode,
810
+ findHostInstanceByFiber: DOMRenderer.findHostInstance,
811
+ // This is an enum because we may add more (e.g. profiler build)
812
+ bundleType: __DEV__ ? 1 : 0,
813
+ version: ReactVersion,
814
+});
815
+
816
+if (__DEV__) {
817
+ if (
818
+ !foundDevTools &&
819
+ ExecutionEnvironment.canUseDOM &&
820
+ window.top === window.self
821
+ ) {
822
+ // If we're in Chrome or Firefox, provide a download link if not installed.
823
+ if (
824
+ (navigator.userAgent.indexOf('Chrome') > -1 &&
825
+ navigator.userAgent.indexOf('Edge') === -1) ||
826
+ navigator.userAgent.indexOf('Firefox') > -1
827
+ ) {
828
+ var showFileUrlMessage = window.location.protocol.indexOf('http') === -1;
829
+ console.info(
830
+ '%cDownload the React DevTools ' +
831
+ 'for a better development experience: ' +
832
+ 'https://fb.me/react-devtools' +
833
+ (showFileUrlMessage
834
+ ? '\nYou might need to use a local HTTP server (instead of file://): ' +
835
+ 'https://fb.me/react-devtools-faq'
836
+ : ''),
837
+ 'font-weight:bold',
838
+ );
839
+ }
840
+ }
841
}
842
843
module.exports = ReactDOMFiber;
src/renderers/native/ReactNativeFiberEntry.js
+8
-10
@@ -116,15 +116,13 @@ if (__DEV__) {
116
);
117
}
118
119
-if (typeof injectInternals === 'function') {
120
- injectInternals({
121
- findFiberByHostInstance: ReactNativeComponentTree.getClosestInstanceFromNode,
122
- findHostInstanceByFiber: ReactNativeFiberRenderer.findHostInstance,
123
- getInspectorDataForViewTag: ReactNativeFiberInspector.getInspectorDataForViewTag,
124
- // This is an enum because we may add more (e.g. profiler build)
125
- bundleType: __DEV__ ? 1 : 0,
126
- version: ReactVersion,
127
- });
128
-}
119
+injectInternals({
120
+ findFiberByHostInstance: ReactNativeComponentTree.getClosestInstanceFromNode,
121
+ findHostInstanceByFiber: ReactNativeFiberRenderer.findHostInstance,
122
+ getInspectorDataForViewTag: ReactNativeFiberInspector.getInspectorDataForViewTag,
123
+ // This is an enum because we may add more (e.g. profiler build)
124
+ bundleType: __DEV__ ? 1 : 0,
125
+ version: ReactVersion,
126
+});
127
128
module.exports = ReactNativeFiber;
src/renderers/shared/fiber/ReactFiberDevToolsHook.js
+54
-38
@@ -21,54 +21,70 @@ if (__DEV__) {
21
var warning = require('fbjs/lib/warning');
22
}
23
24
-let rendererID = null;
25
-let injectInternals = null;
26
-let onCommitRoot = null;
27
-let onCommitUnmount = null;
28
-if (
29
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
30
- __REACT_DEVTOOLS_GLOBAL_HOOK__.supportsFiber
31
-) {
32
- let {
33
- inject,
34
- onCommitFiberRoot,
35
- onCommitFiberUnmount,
36
- } = __REACT_DEVTOOLS_GLOBAL_HOOK__;
24
+let onCommitFiberRoot = null;
25
+let onCommitFiberUnmount = null;
26
+let hasLoggedError = false;
27
38
- injectInternals = function(internals: Object) {
39
- if (__DEV__) {
40
- warning(rendererID == null, 'Cannot inject into DevTools twice.');
41
- }
42
- rendererID = inject(internals);
43
- };
44
-
45
- onCommitRoot = function(root: FiberRoot) {
46
- if (rendererID == null) {
47
- return;
48
- }
28
+function catchErrors(fn) {
29
+ return function(arg) {
30
try {
50
- onCommitFiberRoot(rendererID, root);
31
+ return fn(arg);
32
} catch (err) {
52
- // Catch all errors because it is unsafe to throw in the commit phase.
53
- if (__DEV__) {
33
+ if (__DEV__ && !hasLoggedError) {
34
+ hasLoggedError = true;
35
warning(false, 'React DevTools encountered an error: %s', err);
36
}
37
}
38
};
39
+}
40
59
- onCommitUnmount = function(fiber: Fiber) {
60
- if (rendererID == null) {
61
- return;
41
+function injectInternals(internals: Object): boolean {
42
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
43
+ // No DevTools
44
+ return false;
45
+ }
46
+ const hook = __REACT_DEVTOOLS_GLOBAL_HOOK__;
47
+ if (!hook.supportsFiber) {
48
+ if (__DEV__) {
49
+ warning(
50
+ false,
51
+ 'The installed version of React DevTools is too old and will not work ' +
52
+ 'with the current version of React. Please update React DevTools. ' +
53
+ 'https://fb.me/react-devtools',
54
+ );
55
}
63
- try {
64
- onCommitFiberUnmount(rendererID, fiber);
65
- } catch (err) {
66
- // Catch all errors because it is unsafe to throw in the commit phase.
67
- if (__DEV__) {
68
- warning(false, 'React DevTools encountered an error: %s', err);
69
- }
56
+ // DevTools exists, even though it doesn't support Fiber.
57
+ return true;
58
+ }
59
+ try {
60
+ const rendererID = hook.inject(internals);
61
+ // We have successfully injected, so now it is safe to set up hooks.
62
+ onCommitFiberRoot = catchErrors(root =>
63
+ hook.onCommitFiberRoot(rendererID, root),
64
+ );
65
+ onCommitFiberUnmount = catchErrors(fiber =>
66
+ hook.onCommitFiberUnmount(rendererID, fiber),
67
+ );
68
+ } catch (err) {
69
+ // Catch all errors because it is unsafe to throw during initialization.
70
+ if (__DEV__) {
71
+ warning(false, 'React DevTools encountered an error: %s.', err);
72
}
71
- };
73
+ }
74
+ // DevTools exists
75
+ return true;
76
+}
77
+
78
+function onCommitRoot(root: FiberRoot) {
79
+ if (typeof onCommitFiberRoot === 'function') {
80
+ onCommitFiberRoot(root);
81
+ }
82
+}
83
+
84
+function onCommitUnmount(fiber: Fiber) {
85
+ if (typeof onCommitFiberUnmount === 'function') {
86
+ onCommitFiberUnmount(fiber);
87
+ }
88
}
89
90
exports.injectInternals = injectInternals;