DevTools: support useEffectEvent and forward-fix experimental prefix support (#32106)
- Adds support for `experimental_useEffectEvent`, now DevTools will be able to display this hook for inspected element - Added a use case to DevTools shell, couldn't add case, because we are using ReactTestRenderer, which has the corresponding flag disabled. - Forward-fix logic for handling `experimental` prefix that was added in https://github.com/facebook/react/pull/32088. 
Ruslan Lesiutin committed
Jan 22, 2025 at 14:15 UTC
b000019578a417ec0a1aeec8bda689db240cb28e
3 files changed
+57
-1
packages/react-debug-tools/src/ReactDebugHooks.js
+23
-1
@@ -127,6 +127,13 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
127
}
128
129
Dispatcher.useId();
130
+
131
+ if (typeof Dispatcher.useResourceEffect === 'function') {
132
+ Dispatcher.useResourceEffect(() => ({}), []);
133
+ }
134
+ if (typeof Dispatcher.useEffectEvent === 'function') {
135
+ Dispatcher.useEffectEvent((args: empty) => {});
136
+ }
137
} finally {
138
readHookLog = hookLog;
139
hookLog = [];
@@ -749,6 +756,20 @@ function useResourceEffect(
756
});
757
}
758
759
+function useEffectEvent<Args, F: (...Array<Args>) => mixed>(callback: F): F {
760
+ nextHook();
761
+ hookLog.push({
762
+ displayName: null,
763
+ primitive: 'EffectEvent',
764
+ stackError: new Error(),
765
+ value: callback,
766
+ debugInfo: null,
767
+ dispatcherHookName: 'EffectEvent',
768
+ });
769
+
770
+ return callback;
771
+}
772
+
773
const Dispatcher: DispatcherType = {
774
use,
775
readContext,
@@ -773,6 +794,7 @@ const Dispatcher: DispatcherType = {
794
useFormState,
795
useActionState,
796
useHostTransitionStatus,
797
+ useEffectEvent,
798
useResourceEffect,
799
};
800
@@ -962,7 +984,7 @@ function parseHookName(functionName: void | string): string {
984
startIndex += 'unstable_'.length;
985
}
986
965
- if (functionName.slice(startIndex).startsWith('unstable_')) {
987
+ if (functionName.slice(startIndex).startsWith('experimental_')) {
988
startIndex += 'experimental_'.length;
989
}
990
packages/react-devtools-shell/src/app/InspectableElements/InspectableElements.js
+2
@@ -19,6 +19,7 @@ import NestedProps from './NestedProps';
19
import SimpleValues from './SimpleValues';
20
import SymbolKeys from './SymbolKeys';
21
import UseMemoCache from './UseMemoCache';
22
+import UseEffectEvent from './UseEffectEvent';
23
24
// TODO Add Immutable JS example
25
@@ -36,6 +37,7 @@ export default function InspectableElements(): React.Node {
37
<CircularReferences />
38
<SymbolKeys />
39
<UseMemoCache />
40
+ <UseEffectEvent />
41
</Fragment>
42
);
43
}
packages/react-devtools-shell/src/app/InspectableElements/UseEffectEvent.js
new
+32
@@ -0,0 +1,32 @@
1
+import * as React from 'react';
2
+
3
+const {experimental_useEffectEvent, useState, useEffect} = React;
4
+
5
+export default function UseEffectEvent(): React.Node {
6
+ return (
7
+ <>
8
+ <SingleHookCase />
9
+ <HookTreeCase />
10
+ </>
11
+ );
12
+}
13
+
14
+function SingleHookCase() {
15
+ const onClick = experimental_useEffectEvent(() => {});
16
+
17
+ return <div onClick={onClick} />;
18
+}
19
+
20
+function useCustomHook() {
21
+ const [state, setState] = useState();
22
+ const onClick = experimental_useEffectEvent(() => {});
23
+ useEffect(() => {});
24
+
25
+ return [state, setState, onClick];
26
+}
27
+
28
+function HookTreeCase() {
29
+ const onClick = useCustomHook();
30
+
31
+ return <div onClick={onClick} />;
32
+}