Fix devtools displaying Anonymous for memo of ref-forwarding components (#17274)
* [react-is] return correct typeOf value of forwardRef * [react-devtools-shared] use correct displayName of memo(forwardRef(Component)) * [react-devtools-shared] add resolveFiberType and resolve fiber type of memo recursively Resolving the fiber type of memo recursively before passing it to getDisplayName will prevent it from displaying "Anonymous" as displayName for components wrapped with both memo and forwardRef: memo(forwardRef(Component)) * rework resolveFiberType
Waseem Dahman committed
Nov 5, 2019 at 17:08 UTC
4f02c93c7cb213355b3c7d2011e531431d1c6dd8
1 file changed
+27
-8
packages/react-devtools-shared/src/backend/renderer.js
+27
-8
@@ -324,19 +324,39 @@ export function getInternalReactConstants(
324
PROFILER_SYMBOL_STRING,
325
SCOPE_NUMBER,
326
SCOPE_SYMBOL_STRING,
327
+ FORWARD_REF_NUMBER,
328
+ FORWARD_REF_SYMBOL_STRING,
329
+ MEMO_NUMBER,
330
+ MEMO_SYMBOL_STRING,
331
} = ReactSymbols;
332
333
+ function resolveFiberType(type: any) {
334
+ // This is to support lazy components with a Promise as the type.
335
+ // see https://github.com/facebook/react/pull/13397
336
+ if (typeof type.then === 'function') {
337
+ return type._reactResult;
338
+ }
339
+ const typeSymbol = getTypeSymbol(type);
340
+ switch (typeSymbol) {
341
+ case MEMO_NUMBER:
342
+ case MEMO_SYMBOL_STRING:
343
+ // recursively resolving memo type in case of memo(forwardRef(Component))
344
+ return resolveFiberType(type.type);
345
+ case FORWARD_REF_NUMBER:
346
+ case FORWARD_REF_SYMBOL_STRING:
347
+ return type.render;
348
+ default:
349
+ return type;
350
+ }
351
+ }
352
+
353
// NOTICE Keep in sync with shouldFilterFiber() and other get*ForFiber methods
354
function getDisplayNameForFiber(fiber: Fiber): string | null {
355
const {elementType, type, tag} = fiber;
356
333
- // This is to support lazy components with a Promise as the type.
334
- // see https://github.com/facebook/react/pull/13397
357
let resolvedType = type;
358
if (typeof type === 'object' && type !== null) {
337
- if (typeof type.then === 'function') {
338
- resolvedType = type._reactResult;
339
- }
359
+ resolvedType = resolveFiberType(type);
360
}
361
362
let resolvedContext: any = null;
@@ -350,8 +370,7 @@ export function getInternalReactConstants(
370
return getDisplayName(resolvedType);
371
case ForwardRef:
372
return (
353
- resolvedType.displayName ||
354
- getDisplayName(resolvedType.render, 'Anonymous')
373
+ resolvedType.displayName || getDisplayName(resolvedType, 'Anonymous')
374
);
375
case HostRoot:
376
return null;
@@ -366,7 +385,7 @@ export function getInternalReactConstants(
385
if (elementType.displayName) {
386
return elementType.displayName;
387
} else {
369
- return getDisplayName(type, 'Anonymous');
388
+ return getDisplayName(resolvedType, 'Anonymous');
389
}
390
case SuspenseComponent:
391
return 'Suspense';