-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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
Match react-devtools display name behavior for React.memo #15313
Conversation
48d8e0a
to
4aa2241
Compare
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.
Can we make getComponentName
accept a fiber instead of an element type? Then we don't have to redo all the logic that we did to create the fiber in the first place.
Oh haha I thought you were @bvaughn. Sorry :D If you want to change the signature of |
@@ -792,6 +792,7 @@ describe('ReactLazy', () => { | |||
Add.defaultProps = { | |||
innerWithDefault: 42, | |||
}; | |||
Add.displayName = 'Add'; |
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.
Let's leave these tests as-is and write a separate one that tests displayName
.
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.
This is only there because the test function matches the display name. Since not every component is a memo component the test would fail.
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.
i.e. this is not there to test displayName
but to prevent refactoring the test.
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.
The alternative would be to use a wildcard matcher in
'Invalid prop `inner` of type `string` supplied to `Add`, expected `number`.', |
instead of expecting an exact component 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.
Let's leave these tests as-is and write a separate one that tests displayName.
Added an explicit test for memo and displayName in 012af53.
I could not use displayName in this test but then I would have to change the test to match *
as the displayName (some components have the memo wrapper some don't). I don't think that's a good idea.
Not sure what else I should do here.
I think the devtools get the name from the fiber as well. If we can use a fiber instead we can we get rid of the component name fork in react-devtools as well? |
@@ -34,10 +34,10 @@ function getWrappedName( | |||
innerType: any, | |||
wrapperName: string, | |||
): string { | |||
const functionName = innerType.displayName || innerType.name || ''; | |||
const innerName = getComponentName(innerType) || ''; |
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.
This may be a bit overkill for render functions of forwardRef
. We could extract the logic of innerName
to the call-site of getComponentName
.
4aa2241
to
012af53
Compare
Not any time soon, since DevTools source lives in a different repo and (more importantly) needs to support multiple versions of React- unlike this help function, which only needs to support the current version at any given time. |
@@ -584,6 +584,7 @@ describe('ReactDebugFiberPerf', () => { | |||
const MemoFoo = React.memo(function Foo() { | |||
return <div />; | |||
}); | |||
MemoFoo.displayName = 'Foo'; |
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.
beginFiberMark
will be called with the initial Fiber. However, in updateMemoComponent
we will upgrade the Fiber to a SimpleMemoComponent
at which point the Fiber is indistinguishable for getComponentName
from a function component because with mutated the type. endFiberMark
will receive a SimpleMemoComponent
and getComponentName
assumes it's a plain function component.
Not sure if this is considered a defect (assuming that the fiber type in beginFiberWork
is the same we get in endFiberWork
). Should we we add something _debugOriginalType
field to the Fiber or rather change react-devtools
to display Foo
rather than Memo(Foo)
? Mutating the Mutating the display name was a terrible idea.displayName
of the type when upgrading the Fiber might also work.
Any thoughts @bvaughn ?
012af53
to
6d9c392
Compare
@@ -119,11 +120,19 @@ const getFiberLabel = ( | |||
} | |||
}; | |||
|
|||
const getFiberName = (fiber: Fiber): string | null => { | |||
if (fiber.tag === SimpleMemoComponent) { | |||
return getComponentName(fiber.elementType); |
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.
Tested
-getComponentName(someFiber.type)
+getComponentName(someFiber.elementType)
on all source files in master
and no test broke. This may be the better option if other types of Fibers change their type
during work i.e. getComponentName
should only be called with element types not fiber types (enforceable with types?).
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.
#15638 would remove the necessity for this branch.
4192198
to
2c6088e
Compare
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution. |
I'll resolve merge conflicts. |
I just ran into this issue and I would love to see this PR make it in! I see that it's been sitting here for some time now. |
I'll resolve the conflicts. Maybe this'll help. |
2c6088e
to
de7878e
Compare
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 3893791:
|
@bvaughn Could you take a look at this? |
de7878e
to
8f816bc
Compare
8f816bc
to
3e6f7f8
Compare
3e6f7f8
to
f30ca94
Compare
@@ -532,7 +532,7 @@ describe('memo', () => { | |||
ReactNoop.render(<MemoComponent optional="foo" />), | |||
).toErrorDev( | |||
'Warning: Failed prop type: The prop `required` is marked as required in ' + | |||
'`Foo`, but its value is `undefined`.\n' + | |||
'`Bar`, but its value is `undefined`.\n' + |
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.
This test was added in #18925 but I don't think this should've been the expected behavior @bvaughn.
For React.memo
we ignore displayName
on the wrapper if we have a displayName
on the wrapped component.
For React.forwardRef
we honor displayName
on the wrapper even if we have displayName
on the wrapped component.
I think it is confusing that React.memo
and React.forwardRef
behave differently with regard to displayName
.
This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated. |
Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! |
Showcase to verify matching behavior with react-devtools: https://codesandbox.io/s/lpx7k7wv4z