-
Notifications
You must be signed in to change notification settings - Fork 47k
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
Fix memo and lazy element types being considered elements #14546
Conversation
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.
It would indeed be a breaking change for enzyme; it’s critical that enzyme (and presumably react dev tools) be able to distinguish lazy and memo, both from each other and from unwrapped elements.
Neither memo nor lazy actually tries to be an invisible wrapper - own properties aren’t copied over, including defaultProps, and including the displayName. In other words, imo if it’s possible to differentiate at runtime, then it must be ergonomic to differentiate using react-is.
So from my understanding there is is currently an asymmetry between e.g.
@ljharb react-devtools has no dependency on react-is. Looks like they're directly using the symbols: https://github.com/facebook/react-devtools/blob/4d30604d971b6969982c1346748c6721def0e618/backend/attachRendererFiber.js
Which is also true for |
I think the introspection should also be possible for forwardRef types. |
forwardRef is typically given a trampoline wrapper function (which is just a function component with a 2nd argument), while memo gets a component directly; that makes memo much easier to introspect. As for lazy, it probably can't be introspected other than by attaching to its Promise. |
Simply knowing that it's "lazy" - and not just a regular old Promise - would be sufficient introspection for enzyme (although providing any sort of info, like a name, would be super helpful too). |
I'm not really following that hole introspection is bad/ok argument. Can you link me some resources that explain that concept and why it might be bad for some compilers? I just can't see the pattern that disallows |
That there's a current lack of consistency doesn't mean the right direction is removing functionality that enzyme depends on. |
I agree with that but I all did was follow the documented path that is currently ignored in the implementation. I'm all for a Edit: |
Hi, I'm having this problem, could it be related? https://github.com/zeit/next.js/issues/6117 |
I did not see this discussion, but I have opened a PR to fix the inconsistent/mistaken behavior: |
Regarding @ljharb's concerns about "removing functionality that enzyme depends on", fixing this inconsistency would not prohibit libraries like Enzyme from using the following pattern: ReactIs.isForwardRef(Thing) ||
ReactIs.isValidElementType(Thing) && ReactIs.isForwardRef(<Thing />) |
I've checked out Enzyme and installed a local build of I think that's because Enzyme is already wrapping values in "fake elements" before passing them to |
I've merged PR #17278 which has this fix as well (along with some other added tests). Sorry for missing this PR earlier. I wasn't tagged on it and I just didn't notice. |
ReactIs.typeOf
is currently returning an element type forlazy
andmemo
even if the given value is not an element (i.e. return value ofReact.createElement
) but and elementType. This is confusing since @sebmarkbage spoke against anelementType
API in #12932 (review).This means that it is currently possible to determine if a given elementType is a lazy or memo component.
This PR changes the following behavior so that lazy and memo behave similar to e.g. forwardRef when passed to
is*
ortypeOf
.I just want to add that I would prefer if
ReactIs.typeOf(Memo)
andReactIs.typeOf(FowardRef)
would return the element type but as far as I understood @sebmarkbage both should returnundefined
.Pinging @ljharb since it sounded like (#14313 (review)) that would be a breaking change for
enzyme
.Related:
#12882 (comment)
or
ReactDOM.createPortal
.