-
Notifications
You must be signed in to change notification settings - Fork 50.2k
Match react-devtools display name behavior for React.memo #15313
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
48d8e0a to
4aa2241
Compare
acdlite
left a comment
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 |
| 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? |
| 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. |
| 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
|
|
||
| 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
| ).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