diff --git a/packages/react-debug-tools/src/ReactDebugHooks.js b/packages/react-debug-tools/src/ReactDebugHooks.js index e6a85b86a89d4..af238d7f71f0a 100644 --- a/packages/react-debug-tools/src/ReactDebugHooks.js +++ b/packages/react-debug-tools/src/ReactDebugHooks.js @@ -39,6 +39,7 @@ type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher; // Used to track hooks called during a render type HookLogEntry = { + displayName: string | null, primitive: string, stackError: Error, value: mixed, @@ -164,6 +165,7 @@ function use(usable: Usable): T { case 'fulfilled': { const fulfilledValue: T = thenable.value; hookLog.push({ + displayName: null, primitive: 'Promise', stackError: new Error(), value: fulfilledValue, @@ -180,6 +182,7 @@ function use(usable: Usable): T { // If this was an uncached Promise we have to abandon this attempt // but we can still emit anything up until this point. hookLog.push({ + displayName: null, primitive: 'Unresolved', stackError: new Error(), value: thenable, @@ -192,6 +195,7 @@ function use(usable: Usable): T { const value = readContext(context); hookLog.push({ + displayName: context.displayName || 'Context', primitive: 'Context (use)', stackError: new Error(), value, @@ -208,6 +212,7 @@ function use(usable: Usable): T { function useContext(context: ReactContext): T { hookLog.push({ + displayName: context.displayName || null, primitive: 'Context', stackError: new Error(), value: context._currentValue, @@ -228,6 +233,7 @@ function useState( initialState() : initialState; hookLog.push({ + displayName: null, primitive: 'State', stackError: new Error(), value: state, @@ -249,6 +255,7 @@ function useReducer( state = init !== undefined ? init(initialArg) : ((initialArg: any): S); } hookLog.push({ + displayName: null, primitive: 'Reducer', stackError: new Error(), value: state, @@ -261,6 +268,7 @@ function useRef(initialValue: T): {current: T} { const hook = nextHook(); const ref = hook !== null ? hook.memoizedState : {current: initialValue}; hookLog.push({ + displayName: null, primitive: 'Ref', stackError: new Error(), value: ref.current, @@ -272,6 +280,7 @@ function useRef(initialValue: T): {current: T} { function useCacheRefresh(): () => void { const hook = nextHook(); hookLog.push({ + displayName: null, primitive: 'CacheRefresh', stackError: new Error(), value: hook !== null ? hook.memoizedState : function refresh() {}, @@ -286,6 +295,7 @@ function useLayoutEffect( ): void { nextHook(); hookLog.push({ + displayName: null, primitive: 'LayoutEffect', stackError: new Error(), value: create, @@ -299,6 +309,7 @@ function useInsertionEffect( ): void { nextHook(); hookLog.push({ + displayName: null, primitive: 'InsertionEffect', stackError: new Error(), value: create, @@ -312,6 +323,7 @@ function useEffect( ): void { nextHook(); hookLog.push({ + displayName: null, primitive: 'Effect', stackError: new Error(), value: create, @@ -334,6 +346,7 @@ function useImperativeHandle( instance = ref.current; } hookLog.push({ + displayName: null, primitive: 'ImperativeHandle', stackError: new Error(), value: instance, @@ -343,6 +356,7 @@ function useImperativeHandle( function useDebugValue(value: any, formatterFn: ?(value: any) => any) { hookLog.push({ + displayName: null, primitive: 'DebugValue', stackError: new Error(), value: typeof formatterFn === 'function' ? formatterFn(value) : value, @@ -353,6 +367,7 @@ function useDebugValue(value: any, formatterFn: ?(value: any) => any) { function useCallback(callback: T, inputs: Array | void | null): T { const hook = nextHook(); hookLog.push({ + displayName: null, primitive: 'Callback', stackError: new Error(), value: hook !== null ? hook.memoizedState[0] : callback, @@ -368,6 +383,7 @@ function useMemo( const hook = nextHook(); const value = hook !== null ? hook.memoizedState[0] : nextCreate(); hookLog.push({ + displayName: null, primitive: 'Memo', stackError: new Error(), value, @@ -388,6 +404,7 @@ function useSyncExternalStore( nextHook(); // Effect const value = getSnapshot(); hookLog.push({ + displayName: null, primitive: 'SyncExternalStore', stackError: new Error(), value, @@ -406,6 +423,7 @@ function useTransition(): [ nextHook(); // State nextHook(); // Callback hookLog.push({ + displayName: null, primitive: 'Transition', stackError: new Error(), value: undefined, @@ -417,6 +435,7 @@ function useTransition(): [ function useDeferredValue(value: T, initialValue?: T): T { const hook = nextHook(); hookLog.push({ + displayName: null, primitive: 'DeferredValue', stackError: new Error(), value: hook !== null ? hook.memoizedState : value, @@ -429,6 +448,7 @@ function useId(): string { const hook = nextHook(); const id = hook !== null ? hook.memoizedState : ''; hookLog.push({ + displayName: null, primitive: 'Id', stackError: new Error(), value: id, @@ -478,6 +498,7 @@ function useOptimistic( state = passthrough; } hookLog.push({ + displayName: null, primitive: 'Optimistic', stackError: new Error(), value: state, @@ -500,6 +521,7 @@ function useFormState( state = initialState; } hookLog.push({ + displayName: null, primitive: 'FormState', stackError: new Error(), value: state, @@ -773,7 +795,7 @@ function buildTree( } prevStack = stack; } - const {primitive, debugInfo} = hook; + const {displayName, primitive, debugInfo} = hook; // For now, the "id" of stateful hooks is just the stateful hook index. // Custom hooks have no ids, nor do non-stateful native hooks (e.g. Context, DebugValue). @@ -788,7 +810,7 @@ function buildTree( // For the time being, only State and Reducer hooks support runtime overrides. const isStateEditable = primitive === 'Reducer' || primitive === 'State'; - const name = primitive === 'Context (use)' ? 'Context' : primitive; + const name = displayName || primitive; const levelChild: HooksNode = { id, isStateEditable, diff --git a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js index a74bbe9ca2817..2a512cc495cf1 100644 --- a/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js +++ b/packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js @@ -772,8 +772,11 @@ describe('ReactHooksInspectionIntegration', () => { it('should inspect the value of the current provider in useContext', () => { const MyContext = React.createContext('default'); + const ThemeContext = React.createContext('default'); + ThemeContext.displayName = 'Theme'; function Foo(props) { const value = React.useContext(MyContext); + React.useContext(ThemeContext); return
{value}
; } const renderer = ReactTestRenderer.create( @@ -799,6 +802,20 @@ describe('ReactHooksInspectionIntegration', () => { "subHooks": [], "value": "contextual", }, + { + "debugInfo": null, + "hookSource": { + "columnNumber": 0, + "fileName": "**", + "functionName": "Foo", + "lineNumber": 0, + }, + "id": null, + "isStateEditable": false, + "name": "Theme", + "subHooks": [], + "value": "default", + }, ] `); });