@samitouri / QOS-React / commits / b000019578

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. ![Screenshot 2025-01-16 at 21 24 12](https://github.com/user-attachments/assets/6fb8ff2a-be47-47b5-bbfc-73d3a586657c)

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 +}