Skip to content
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

Closed
wants to merge 2 commits into from

Conversation

eps1lon
Copy link
Collaborator

@eps1lon eps1lon commented Apr 3, 2019

// anonymous render
React.memo(() => null)
- Component
+ Memo
// named render
React.memo(function Inner() { return null })
- Inner
+ Memo(Inner)

Showcase to verify matching behavior with react-devtools: https://codesandbox.io/s/lpx7k7wv4z

Copy link
Collaborator

@acdlite acdlite left a 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.

@acdlite
Copy link
Collaborator

acdlite commented Apr 3, 2019

Oh haha I thought you were @bvaughn. Sorry :D If you want to change the signature of getComponentType then that's fine, but what you have is fine, too.

@@ -792,6 +792,7 @@ describe('ReactLazy', () => {
Add.defaultProps = {
innerWithDefault: 42,
};
Add.displayName = 'Add';
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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.

@eps1lon
Copy link
Collaborator Author

eps1lon commented Apr 3, 2019

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) || '';
Copy link
Collaborator Author

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.

@eps1lon eps1lon force-pushed the feat/memo-component-name branch from 4aa2241 to 012af53 Compare April 9, 2019 18:07
@bvaughn
Copy link
Contributor

bvaughn commented Apr 11, 2019

If we can use a fiber instead we can we get rid of the component name fork in react-devtools as well?

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';
Copy link
Collaborator Author

@eps1lon eps1lon Apr 14, 2019

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 displayName of the type when upgrading the Fiber might also work. Mutating the display name was a terrible idea.

Any thoughts @bvaughn ?

@eps1lon eps1lon force-pushed the feat/memo-component-name branch from 012af53 to 6d9c392 Compare April 14, 2019 11:33
@@ -119,11 +120,19 @@ const getFiberLabel = (
}
};

const getFiberName = (fiber: Fiber): string | null => {
if (fiber.tag === SimpleMemoComponent) {
return getComponentName(fiber.elementType);
Copy link
Collaborator Author

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?).

Copy link
Collaborator Author

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.

@sizebot
Copy link

sizebot commented Aug 29, 2019

No significant bundle size changes to report.

Generated by 🚫 dangerJS against 2c6088e

@Airkro
Copy link

Airkro commented Sep 12, 2019

forwardRef should do the same.

@stale
Copy link

stale bot commented Jan 9, 2020

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.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Jan 9, 2020
@eps1lon
Copy link
Collaborator Author

eps1lon commented Jan 10, 2020

I'll resolve merge conflicts.

@stale stale bot removed the Resolution: Stale Automatically closed due to inactivity label Jan 10, 2020
@alflennik
Copy link

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.

@eps1lon
Copy link
Collaborator Author

eps1lon commented Feb 27, 2020

I'll resolve the conflicts. Maybe this'll help.

@eps1lon eps1lon force-pushed the feat/memo-component-name branch from 2c6088e to de7878e Compare March 1, 2020 17:27
@codesandbox-ci
Copy link

codesandbox-ci bot commented Mar 1, 2020

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:

Sandbox Source
hungry-murdock-13ddl Configuration
React.memo display name in react and react-devtools PR

@sizebot
Copy link

sizebot commented Mar 1, 2020

No significant bundle size changes to report.

Size changes (experimental)

Generated by 🚫 dangerJS against 3893791

@sizebot
Copy link

sizebot commented Mar 1, 2020

No significant bundle size changes to report.

Size changes (stable)

Generated by 🚫 dangerJS against 3893791

@eps1lon
Copy link
Collaborator Author

eps1lon commented Mar 5, 2020

@bvaughn Could you take a look at this?

@eps1lon eps1lon force-pushed the feat/memo-component-name branch from de7878e to 8f816bc Compare April 14, 2020 19:54
@eps1lon eps1lon force-pushed the feat/memo-component-name branch from 8f816bc to 3e6f7f8 Compare May 14, 2020 18:16
@eps1lon eps1lon force-pushed the feat/memo-component-name branch from 3e6f7f8 to f30ca94 Compare May 25, 2020 04:33
@@ -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' +
Copy link
Collaborator Author

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.

@stale
Copy link

stale bot commented Aug 23, 2020

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.

@stale stale bot added the Resolution: Stale Automatically closed due to inactivity label Aug 23, 2020
@stale
Copy link

stale bot commented Aug 30, 2020

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!

@stale stale bot closed this Aug 30, 2020
@eps1lon eps1lon deleted the feat/memo-component-name branch June 30, 2021 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed Resolution: Stale Automatically closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants