-
Notifications
You must be signed in to change notification settings - Fork 47.5k
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
allow react memo component can set displayName multiple times #20659
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
displayName
from 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
displayName
multiple times, because it's standalone getter/setter property.React devtools getDisplayName logic
PR for what ?
React.forwardRef
andReact.memo
have 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.