@samitouri / QOS-React-1 / commits / aed00dacfb

devtools: Use context displayName for context hook name (#25954)

Sebastian Silbermann committed Feb 24, 2024 at 11:54 UTC aed00dacfb79d17c53218404c52b1c7aa59c4a89
2 files changed +41 -2
packages/react-debug-tools/src/ReactDebugHooks.js
+24 -2
@@ -39,6 +39,7 @@ type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher;
39 // Used to track hooks called during a render
40
41 type HookLogEntry = {
42 + displayName: string | null,
43 primitive: string,
44 stackError: Error,
45 value: mixed,
@@ -171,6 +172,7 @@ function use<T>(usable: Usable<T>): T {
172 case 'fulfilled': {
173 const fulfilledValue: T = thenable.value;
174 hookLog.push({
175 + displayName: null,
176 primitive: 'Promise',
177 stackError: new Error(),
178 value: fulfilledValue,
@@ -187,6 +189,7 @@ function use<T>(usable: Usable<T>): T {
189 // If this was an uncached Promise we have to abandon this attempt
190 // but we can still emit anything up until this point.
191 hookLog.push({
192 + displayName: null,
193 primitive: 'Unresolved',
194 stackError: new Error(),
195 value: thenable,
@@ -199,6 +202,7 @@ function use<T>(usable: Usable<T>): T {
202 const value = readContext(context);
203
204 hookLog.push({
205 + displayName: context.displayName || 'Context',
206 primitive: 'Context (use)',
207 stackError: new Error(),
208 value,
@@ -215,6 +219,7 @@ function use<T>(usable: Usable<T>): T {
219
220 function useContext<T>(context: ReactContext<T>): T {
221 hookLog.push({
222 + displayName: context.displayName || null,
223 primitive: 'Context',
224 stackError: new Error(),
225 value: context._currentValue,
@@ -235,6 +240,7 @@ function useState<S>(
240 initialState()
241 : initialState;
242 hookLog.push({
243 + displayName: null,
244 primitive: 'State',
245 stackError: new Error(),
246 value: state,
@@ -256,6 +262,7 @@ function useReducer<S, I, A>(
262 state = init !== undefined ? init(initialArg) : ((initialArg: any): S);
263 }
264 hookLog.push({
265 + displayName: null,
266 primitive: 'Reducer',
267 stackError: new Error(),
268 value: state,
@@ -268,6 +275,7 @@ function useRef<T>(initialValue: T): {current: T} {
275 const hook = nextHook();
276 const ref = hook !== null ? hook.memoizedState : {current: initialValue};
277 hookLog.push({
278 + displayName: null,
279 primitive: 'Ref',
280 stackError: new Error(),
281 value: ref.current,
@@ -279,6 +287,7 @@ function useRef<T>(initialValue: T): {current: T} {
287 function useCacheRefresh(): () => void {
288 const hook = nextHook();
289 hookLog.push({
290 + displayName: null,
291 primitive: 'CacheRefresh',
292 stackError: new Error(),
293 value: hook !== null ? hook.memoizedState : function refresh() {},
@@ -293,6 +302,7 @@ function useLayoutEffect(
302 ): void {
303 nextHook();
304 hookLog.push({
305 + displayName: null,
306 primitive: 'LayoutEffect',
307 stackError: new Error(),
308 value: create,
@@ -306,6 +316,7 @@ function useInsertionEffect(
316 ): void {
317 nextHook();
318 hookLog.push({
319 + displayName: null,
320 primitive: 'InsertionEffect',
321 stackError: new Error(),
322 value: create,
@@ -319,6 +330,7 @@ function useEffect(
330 ): void {
331 nextHook();
332 hookLog.push({
333 + displayName: null,
334 primitive: 'Effect',
335 stackError: new Error(),
336 value: create,
@@ -341,6 +353,7 @@ function useImperativeHandle<T>(
353 instance = ref.current;
354 }
355 hookLog.push({
356 + displayName: null,
357 primitive: 'ImperativeHandle',
358 stackError: new Error(),
359 value: instance,
@@ -350,6 +363,7 @@ function useImperativeHandle<T>(
363
364 function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
365 hookLog.push({
366 + displayName: null,
367 primitive: 'DebugValue',
368 stackError: new Error(),
369 value: typeof formatterFn === 'function' ? formatterFn(value) : value,
@@ -360,6 +374,7 @@ function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
374 function useCallback<T>(callback: T, inputs: Array<mixed> | void | null): T {
375 const hook = nextHook();
376 hookLog.push({
377 + displayName: null,
378 primitive: 'Callback',
379 stackError: new Error(),
380 value: hook !== null ? hook.memoizedState[0] : callback,
@@ -375,6 +390,7 @@ function useMemo<T>(
390 const hook = nextHook();
391 const value = hook !== null ? hook.memoizedState[0] : nextCreate();
392 hookLog.push({
393 + displayName: null,
394 primitive: 'Memo',
395 stackError: new Error(),
396 value,
@@ -395,6 +411,7 @@ function useSyncExternalStore<T>(
411 nextHook(); // Effect
412 const value = getSnapshot();
413 hookLog.push({
414 + displayName: null,
415 primitive: 'SyncExternalStore',
416 stackError: new Error(),
417 value,
@@ -413,6 +430,7 @@ function useTransition(): [
430 nextHook(); // State
431 nextHook(); // Callback
432 hookLog.push({
433 + displayName: null,
434 primitive: 'Transition',
435 stackError: new Error(),
436 value: undefined,
@@ -424,6 +442,7 @@ function useTransition(): [
442 function useDeferredValue<T>(value: T, initialValue?: T): T {
443 const hook = nextHook();
444 hookLog.push({
445 + displayName: null,
446 primitive: 'DeferredValue',
447 stackError: new Error(),
448 value: hook !== null ? hook.memoizedState : value,
@@ -436,6 +455,7 @@ function useId(): string {
455 const hook = nextHook();
456 const id = hook !== null ? hook.memoizedState : '';
457 hookLog.push({
458 + displayName: null,
459 primitive: 'Id',
460 stackError: new Error(),
461 value: id,
@@ -485,6 +505,7 @@ function useOptimistic<S, A>(
505 state = passthrough;
506 }
507 hookLog.push({
508 + displayName: null,
509 primitive: 'Optimistic',
510 stackError: new Error(),
511 value: state,
@@ -507,6 +528,7 @@ function useFormState<S, P>(
528 state = initialState;
529 }
530 hookLog.push({
531 + displayName: null,
532 primitive: 'FormState',
533 stackError: new Error(),
534 value: state,
@@ -780,7 +802,7 @@ function buildTree(
802 }
803 prevStack = stack;
804 }
783 - const {primitive, debugInfo} = hook;
805 + const {displayName, primitive, debugInfo} = hook;
806
807 // For now, the "id" of stateful hooks is just the stateful hook index.
808 // Custom hooks have no ids, nor do non-stateful native hooks (e.g. Context, DebugValue).
@@ -795,7 +817,7 @@ function buildTree(
817
818 // For the time being, only State and Reducer hooks support runtime overrides.
819 const isStateEditable = primitive === 'Reducer' || primitive === 'State';
798 - const name = primitive === 'Context (use)' ? 'Context' : primitive;
820 + const name = displayName || primitive;
821 const levelChild: HooksNode = {
822 id,
823 isStateEditable,
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js
+17
@@ -772,8 +772,11 @@ describe('ReactHooksInspectionIntegration', () => {
772
773 it('should inspect the value of the current provider in useContext', () => {
774 const MyContext = React.createContext('default');
775 + const ThemeContext = React.createContext('default');
776 + ThemeContext.displayName = 'Theme';
777 function Foo(props) {
778 const value = React.useContext(MyContext);
779 + React.useContext(ThemeContext);
780 return <div>{value}</div>;
781 }
782 const renderer = ReactTestRenderer.create(
@@ -799,6 +802,20 @@ describe('ReactHooksInspectionIntegration', () => {
802 "subHooks": [],
803 "value": "contextual",
804 },
805 + {
806 + "debugInfo": null,
807 + "hookSource": {
808 + "columnNumber": 0,
809 + "fileName": "**",
810 + "functionName": "Foo",
811 + "lineNumber": 0,
812 + },
813 + "id": null,
814 + "isStateEditable": false,
815 + "name": "Theme",
816 + "subHooks": [],
817 + "value": "default",
818 + },
819 ]
820 `);
821 });