-
Notifications
You must be signed in to change notification settings - Fork 4.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
WordPressComponentProps: Only add refs when they are actually added #43610
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.
Code changes look good and the project builds correctly, including Storybook.
I don't love that
WordPressComponentProps
now has four parameters, but in the end it seemed easier to maintain than creating a separateWordPressComponentPropsWithoutRef
type.
I'm also not in love with the 4th parameter — it's not easy to discover, and it forces devs to define the previous parameters (even if they otherwise could have been omitted in favor of their default value).
Adding a WordPressComponentPropsWithoutRef
would also align better with the fact that React exposes a ComponentPropsWithRef
and a ComponentPropsWithoutRef
.
How much more complicated would the implementation be, if we had to go that way?
Size Change: 0 B Total Size: 1.24 MB ℹ️ View Unchanged
|
Thanks for nudging me to try harder, I think I uncovered a critical detail that was straight-up wrong. As a result, it's much more simpler now. I've updated the PR description, and will add a few inline comments. |
// @ts-expect-error | ||
export const View: WordPressComponent< | ||
'div', | ||
ViewProps & RefAttributes< any > | ||
> = styled.div``; | ||
|
||
View.selector = '.components-view'; | ||
View.displayName = 'View'; |
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.
Here we explicitly add the ref
because styled.div
accepts it.
(This part is kind of hacky to begin with 🙁 I might be able to untangle it if I understood what the selector
property is for...)
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 might be able to untangle it
What do you have in mind?
if I understood what the
selector
property is for...
I believe it's used in contextConnect
:
gutenberg/packages/components/src/ui/context/context-connect.ts
Lines 76 to 77 in d64dab9
// @ts-ignore WordPressComponent property | |
WrappedComponent.selector = `.${ getStyledClassNameFromKey( namespace ) }`; |
Explanation:
gutenberg/packages/components/src/ui/context/wordpress-component.ts
Lines 39 to 47 in 515928d
/** | |
* A CSS selector used to fake component interpolation in styled components | |
* for components not generated by `styled`. Anything passed to `contextConnect` | |
* will get this property. | |
* | |
* We restrict it to a class to align with the already existing class names that | |
* are generated by the context system. | |
*/ | |
selector: `.${ string }`; |
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.
component interpolation in styled components
Does this refer to this kind of thing? 👇
styled.div`
${ MyComponent } {
color: black;
}
`;
I might be able to untangle it
What do you have in mind?
A lot of the ts-ignore
s have to do with the fact that the WordPressComponent
type defines the custom properties select
and __contextSystemKey__
as required. Things could be easier if they were marked as optional.
Another thing is this line:
let mergedNamespace = WrappedComponent[ CONNECT_STATIC_NAMESPACE ] || [ |
I don't see how WrappedComponent
could ever have a __contextSystemKey__
property at that point. If someone ran the same component through multiple contextConnect
s? So either I don't fully understand what's going on, or this "merged namespaces" stuff can be cut.
In any case, these concerns are in follow-up territory.
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.
In any case, these concerns are in follow-up territory.
Definitely, let's discuss in a follow-up!
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 also think that things look much better!
Just a few questions left:
- Should we wait for any more progress happening in Components: Add contextConnectWithoutRef() to bypass ref forwarding #43611, before merging this PR?
- Are there any components that already accept
ref
as a normal prop (i.e. without being explicitly wrapped inforwardRef
)? If so, is the plan for them to refactor them gradually as we convert them to TypeScript, or should we refactor them as part of this PR? - Do we need to make any changes to the contributing guidelines, especially re. handling
ref
s as part of the TypeScript migration ?
// @ts-expect-error | ||
export const View: WordPressComponent< | ||
'div', | ||
ViewProps & RefAttributes< any > | ||
> = styled.div``; | ||
|
||
View.selector = '.components-view'; | ||
View.displayName = 'View'; |
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 might be able to untangle it
What do you have in mind?
if I understood what the
selector
property is for...
I believe it's used in contextConnect
:
gutenberg/packages/components/src/ui/context/context-connect.ts
Lines 76 to 77 in d64dab9
// @ts-ignore WordPressComponent property | |
WrappedComponent.selector = `.${ getStyledClassNameFromKey( namespace ) }`; |
Explanation:
gutenberg/packages/components/src/ui/context/wordpress-component.ts
Lines 39 to 47 in 515928d
/** | |
* A CSS selector used to fake component interpolation in styled components | |
* for components not generated by `styled`. Anything passed to `contextConnect` | |
* will get this property. | |
* | |
* We restrict it to a class to align with the already existing class names that | |
* are generated by the context system. | |
*/ | |
selector: `.${ string }`; |
Nope, we're at a good point to merge 👍
Good question. The good thing about the approach in this PR is that it immediately corrects these mistakes, with no refactoring required. Sweeping the components package, I found these components to accept
From now on, a
Good point! I think we should remove the step about adding a |
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 believe this PR needs a rebase to include this change to unblock e2e tests
I think we should remove the step about adding a forwardRef/contextConnect as part of the TS migration. They can be added when driven by an actual need, but shouldn't be part of the standard migration. Does that sound right?
Sounds good to me 🆗
Good question. The good thing about the approach in this PR is that it immediately corrects these mistakes, with no refactoring required.
That sounds great, thank you for checking! As far as no components are expecting them to accept a ref
, then we're good!
🚀
What?
Remove the
ref
prop fromWordPressComponentProps
.The ad hoc
Omit
s on the following components have been removed:Why?
The
WordPressComponentProps
type always added aref
prop, even though theprops
object of aForwardRefRenderFunction
(i.e. the function to be passed toforwardRef()
) should never even contain aref
prop.The
ref
prop should only be mixed into theprops
object type only after the component is wrapped byforwardRef()
.How?
Don't include the
ref
inWordPressComponentProps
, but instead allow it to be added fromWordPressComponentFromProps
orWordPressComponent
.Testing Instructions
npm run storybook:dev
ref
prop is still omitted from the props table.