Memoized components should forward displayName
See original GitHub issueDo you want to request a feature or report a bug?
I’d like to report a bug.
What is the current behavior?
First of all, thanks for the great work on fixing https://github.com/facebook/react/issues/14807. However there is still an issue with the current implementation.
React.memo
does not forward displayName for tests. In snapshots, components display as <Component />
and string assertions such as .find('MyMemoizedComponent')
won’t work.
What is the expected behavior?
React.memo
should forward displayName for the test renderer.
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
- React 16.8.5
- Jest 24.5.0
- enzyme 3.9.0
- enzyme-adapter-react-16 1.11.2
N.B. - Potentially related to https://github.com/facebook/react/issues/14319, but this is related to the more recent changes to support memo
in the test renderer. Please close if needed, I’m quite new here!
I’d be happy to submit a PR if the issue is not too complex to look into 😄
Issue Analytics
- State:
- Created 4 years ago
- Reactions:19
- Comments:16 (7 by maintainers)
Still an issue
I peeked into the memo source. This is a bit more complex than we thought.
Normally, most HOCs return a component and set a displayName based on
displayName || name
.However
React.memo
does not return a component. It returns an object with$$typeof: REACT_MEMO_TYPE
andtype
.So there’s no simple “wrap the displayName like other HOCs” because the result is not a component. It’s an informational object that React understands how to process and is closer to the the ReactElement returned by createElement than it is to a component.
I see two potential solutions.
Solution 1: Hack a displayName in
The quick and dirty fix would be to modify
memo
’s$$typeof: REACT_MEMO_TYPE
object to include adisplayName
property.This feels like a hack because the memo object is technically not a component and would be equivalent to adding a displayName to
Fragment
and the other special component types. However this would most likely work pretty universally.Solution 2: Expect wrappers to handle this
The alternative is to expect that any HOC wrappers will handle memo themselves. So when they see the
$$typeof: REACT_MEMO_TYPE
they should resolve something similar tomemo(${getComponentName(component.type)})
.However if this is the plan I do not think it would be fair to make 3rd party libraries all handle this themselves.
memo
isn’t the only issue here.forwardRef
does something similar, there are a bunch of other special components, and it’s entirely possible there will be a new HOC-like built-in special component in the future. So I think it would be fair in this instance for React to provide an official method of getting the component name that will work with all these special components.React actually already has this internally. getComponentName.js contains both a
getComponentName
function that handlesname
,displayName
,memo
,Fragment
, and more. And even agetWrappedName
helper.For this solution
getComponentName
andgetWrappedName
(perhaps rename to wrapComponentName) should be exported officially from somewhere. Either this should be exported from
reactor we should have a new package similar to
react-isthat exports
getComponentNameand
getWrappedName`.recompose
’sgetDisplayName
will need to be updated to use the officialgetComponentName
– as it’s still used by a lot of people. Likewise other libraries that do the same like@material-ui/utils
will need updating.This is basically #14319.