Skip to content

Commit

Permalink
devtools: Use context displayName for context hook name (#25954)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon authored Feb 24, 2024
1 parent 118ad2a commit aed00da
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
26 changes: 24 additions & 2 deletions packages/react-debug-tools/src/ReactDebugHooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -171,6 +172,7 @@ function use<T>(usable: Usable<T>): T {
case 'fulfilled': {
const fulfilledValue: T = thenable.value;
hookLog.push({
displayName: null,
primitive: 'Promise',
stackError: new Error(),
value: fulfilledValue,
Expand All @@ -187,6 +189,7 @@ function use<T>(usable: Usable<T>): 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,
Expand All @@ -199,6 +202,7 @@ function use<T>(usable: Usable<T>): T {
const value = readContext(context);

hookLog.push({
displayName: context.displayName || 'Context',
primitive: 'Context (use)',
stackError: new Error(),
value,
Expand All @@ -215,6 +219,7 @@ function use<T>(usable: Usable<T>): T {

function useContext<T>(context: ReactContext<T>): T {
hookLog.push({
displayName: context.displayName || null,
primitive: 'Context',
stackError: new Error(),
value: context._currentValue,
Expand All @@ -235,6 +240,7 @@ function useState<S>(
initialState()
: initialState;
hookLog.push({
displayName: null,
primitive: 'State',
stackError: new Error(),
value: state,
Expand All @@ -256,6 +262,7 @@ function useReducer<S, I, A>(
state = init !== undefined ? init(initialArg) : ((initialArg: any): S);
}
hookLog.push({
displayName: null,
primitive: 'Reducer',
stackError: new Error(),
value: state,
Expand All @@ -268,6 +275,7 @@ function useRef<T>(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,
Expand All @@ -279,6 +287,7 @@ function useRef<T>(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() {},
Expand All @@ -293,6 +302,7 @@ function useLayoutEffect(
): void {
nextHook();
hookLog.push({
displayName: null,
primitive: 'LayoutEffect',
stackError: new Error(),
value: create,
Expand All @@ -306,6 +316,7 @@ function useInsertionEffect(
): void {
nextHook();
hookLog.push({
displayName: null,
primitive: 'InsertionEffect',
stackError: new Error(),
value: create,
Expand All @@ -319,6 +330,7 @@ function useEffect(
): void {
nextHook();
hookLog.push({
displayName: null,
primitive: 'Effect',
stackError: new Error(),
value: create,
Expand All @@ -341,6 +353,7 @@ function useImperativeHandle<T>(
instance = ref.current;
}
hookLog.push({
displayName: null,
primitive: 'ImperativeHandle',
stackError: new Error(),
value: instance,
Expand All @@ -350,6 +363,7 @@ function useImperativeHandle<T>(

function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
hookLog.push({
displayName: null,
primitive: 'DebugValue',
stackError: new Error(),
value: typeof formatterFn === 'function' ? formatterFn(value) : value,
Expand All @@ -360,6 +374,7 @@ function useDebugValue(value: any, formatterFn: ?(value: any) => any) {
function useCallback<T>(callback: T, inputs: Array<mixed> | void | null): T {
const hook = nextHook();
hookLog.push({
displayName: null,
primitive: 'Callback',
stackError: new Error(),
value: hook !== null ? hook.memoizedState[0] : callback,
Expand All @@ -375,6 +390,7 @@ function useMemo<T>(
const hook = nextHook();
const value = hook !== null ? hook.memoizedState[0] : nextCreate();
hookLog.push({
displayName: null,
primitive: 'Memo',
stackError: new Error(),
value,
Expand All @@ -395,6 +411,7 @@ function useSyncExternalStore<T>(
nextHook(); // Effect
const value = getSnapshot();
hookLog.push({
displayName: null,
primitive: 'SyncExternalStore',
stackError: new Error(),
value,
Expand All @@ -413,6 +430,7 @@ function useTransition(): [
nextHook(); // State
nextHook(); // Callback
hookLog.push({
displayName: null,
primitive: 'Transition',
stackError: new Error(),
value: undefined,
Expand All @@ -424,6 +442,7 @@ function useTransition(): [
function useDeferredValue<T>(value: T, initialValue?: T): T {
const hook = nextHook();
hookLog.push({
displayName: null,
primitive: 'DeferredValue',
stackError: new Error(),
value: hook !== null ? hook.memoizedState : value,
Expand All @@ -436,6 +455,7 @@ function useId(): string {
const hook = nextHook();
const id = hook !== null ? hook.memoizedState : '';
hookLog.push({
displayName: null,
primitive: 'Id',
stackError: new Error(),
value: id,
Expand Down Expand Up @@ -485,6 +505,7 @@ function useOptimistic<S, A>(
state = passthrough;
}
hookLog.push({
displayName: null,
primitive: 'Optimistic',
stackError: new Error(),
value: state,
Expand All @@ -507,6 +528,7 @@ function useFormState<S, P>(
state = initialState;
}
hookLog.push({
displayName: null,
primitive: 'FormState',
stackError: new Error(),
value: state,
Expand Down Expand Up @@ -780,7 +802,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).
Expand All @@ -795,7 +817,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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <div>{value}</div>;
}
const renderer = ReactTestRenderer.create(
Expand All @@ -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",
},
]
`);
});
Expand Down

0 comments on commit aed00da

Please sign in to comment.