- 
                Notifications
    
You must be signed in to change notification settings  - Fork 49.7k
 
allow react memo component can set displayName multiple times #20659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| 
          
 Comparing: 3c21aa8...44d947a Critical size changesIncludes critical production bundles, as well as any change greater than 2%: 
 Significant size changesIncludes any change greater than 0.2%: (No significant changes)  | 
    
| 
           I'll add myself as a reviewer to reminder myself at some point in the future but I'm pretty swamped right now so I'm not committing to look any time soon. It doesn't hurt anything to leave the PR open so I suggest you just do that. :)  | 
    
| 
           Sorry, it's my fault. Thanks for your advices.  | 
    
| 
           Is there a timeline when this might be merged?  | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| console.error( | ||
| "%s: is not valid displayName type, React memo's displayName should be a string", | ||
| typeof name, | ||
| ); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not follow the exact behavior of forwardRef here?
react/packages/react/src/ReactForwardRef.js
Lines 51 to 64 in a0d6b15
| let ownName; | |
| Object.defineProperty(elementType, 'displayName', { | |
| enumerable: false, | |
| configurable: true, | |
| get: function() { | |
| return ownName; | |
| }, | |
| set: function(name) { | |
| ownName = name; | |
| if (render.displayName == null) { | |
| render.displayName = name; | |
| } | |
| }, | |
| }); | 
Specifically, only set type.displayName = name if it's not already type.displayName === null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
react/packages/react-devtools-shared/src/backend/renderer.js
Lines 379 to 392 in a0d6b15
| function resolveFiberType(type: any) { | |
| const typeSymbol = getTypeSymbol(type); | |
| switch (typeSymbol) { | |
| case MEMO_NUMBER: | |
| case MEMO_SYMBOL_STRING: | |
| // recursively resolving memo type in case of memo(forwardRef(Component)) | |
| return resolveFiberType(type.type); | |
| case FORWARD_REF_NUMBER: | |
| case FORWARD_REF_SYMBOL_STRING: | |
| return type.render; | |
| default: | |
| return type; | |
| } | |
| } | 
If we set ownName we get the ownName(ownName) as displayName and otherwise we use type.render's displayName or name.
react/packages/react-devtools-shared/src/backend/renderer.js
Lines 414 to 419 in a0d6b15
| case ForwardRef: | |
| // Mirror https://github.com/facebook/react/blob/7c21bf72ace77094fd1910cc350a548287ef8350/packages/shared/getComponentName.js#L27-L37 | |
| return ( | |
| (type && type.displayName) || | |
| getDisplayName(resolvedType, 'Anonymous') | |
| ); | 
Yep, you are right, we need change the forwardRef logic as same as memoComponent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We just want allow user set displayName multi time, the common scenario is that user use third party react library such as mobx-react, mobx-react use hoc to wrap component and use memo to optimize rende performance. and now user can't set custom displayName to debug . for example (mobxjs/mobx#2721
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My point was that I don't understand why we were making the implementation of forwardRef and memo different.
TBH I'm not sure that either one modifying type.displayName is a good idea b'c that's a side effect. We do it because it helps with component stacks but I'm not sure that's the best workaround there either.
For instance:
function MyComponent() {
  // ...
}
const MyMemoizedComponent = React.memo(MyComponent);
MyMemoizedComponent.displayName = 'Blah';
// Now if I render <MyComponent> it will also have a displayName of "blah"
// That doesn't seem good.It's true that forwardRef and memo currently have different behaviors in component stacks and that's not good either. To me, this indicates that the right place to make this change is where we read the names rather than here. So I'm talking about getComponentNameFromType 😄
Maybe it would be clearer for me to post a PR with an alternate idea for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #21392
| 
           closed, see bvaughn's alternative PR #21392  | 
    

TL;DR
displayNamefrom memoized components should be taken into account in DevTools #18026 (comment)React displayName
question: can we set component displayName multiple times?
answer: ⬇️
Deep Investigation
React.forwardRef displayName behavior
React forwardRef Component actually
You can modilfy
displayNamemultiple times, because it's standalone getter/setter property.React devtools getDisplayName logic
PR for what ?
React.forwardRefandReact.memohave same behaviorTest Plan
Add a new unit test and modify a exist unit test. Need @bvaughn and @eps1lon check it.
append comment
welcome any advices helpful, I'm not ReactJS expert so maybe I do something wrong.