-
Notifications
You must be signed in to change notification settings - Fork 2.9k
chore(react-utilities): slot API react v17/18 support #31548
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
base: master
Are you sure you want to change the base?
chore(react-utilities): slot API react v17/18 support #31548
Conversation
Perf Analysis (
|
| Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
|---|---|---|---|---|---|
| FluentProviderWithTheme | virtual-rerender | 32 | 38 | 10 | Possible regression |
All results
| Scenario | Render type | Master Ticks | PR Ticks | Iterations | Status |
|---|---|---|---|---|---|
| Avatar | mount | 630 | 622 | 5000 | |
| Button | mount | 303 | 309 | 5000 | |
| Field | mount | 1158 | 1128 | 5000 | |
| FluentProvider | mount | 683 | 704 | 5000 | |
| FluentProviderWithTheme | mount | 84 | 85 | 10 | |
| FluentProviderWithTheme | virtual-rerender | 32 | 38 | 10 | Possible regression |
| FluentProviderWithTheme | virtual-rerender-with-unmount | 81 | 77 | 10 | |
| MakeStyles | mount | 865 | 871 | 50000 | |
| Persona | mount | 1786 | 1737 | 5000 | |
| SpinButton | mount | 1369 | 1421 | 5000 | |
| SwatchPicker | mount | 1663 | 1640 | 5000 |
|
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. |
📊 Bundle size reportUnchanged fixtures
|
3421071 to
9a444bd
Compare
3279340 to
a54bb34
Compare
c906ba8 to
fcc5a3b
Compare
b7ee301 to
b2e0476
Compare
ce2cfbb to
4b3bba1
Compare
4b3bba1 to
c25417c
Compare
|
Pull request demo site: URL |
📊 Bundle size reportUnchanged fixtures
|
1e8b5f4 to
dd89673
Compare
dd89673 to
393bfec
Compare
| @@ -0,0 +1,7 @@ | |||
| { | |||
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.
🕵🏾♀️ visual regressions to review in the fluentuiv9 Visual Regression Report
Avatar Converged 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| Avatar Converged.badgeMask - RTL.normal.chromium.png | 2 | Changed |
| */ | ||
| export function getSlots<R extends SlotPropsRecord>( | ||
| state: ComponentState<R>, | ||
| state: unknown, |
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.
fyi: all of these functions have bad design as they use misused generics. would be great to address this in this PR as we are introducing breaking changes on type already.
see https://typescript-eslint.io/rules/no-unnecessary-type-parameters/ and https://typescript-eslint.io/rules/no-unnecessary-type-constraint/
| @@ -1,9 +1,10 @@ | |||
| import * as React from 'react'; | |||
| import { SlotComponentType, UnknownSlotProps } from '@fluentui/react-utilities'; | |||
| import { SlotComponentType } from '@fluentui/react-utilities'; | |||
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.
| import { SlotComponentType } from '@fluentui/react-utilities'; | |
| import type { SlotComponentType } from '@fluentui/react-utilities'; |
| // eslint-disable-next-line @typescript-eslint/no-deprecated | ||
| export const useARIAButtonShorthand: ResolveShorthandFunction<ARIAButtonSlotProps> = (value, options) => { | ||
| // eslint-disable-next-line @typescript-eslint/no-deprecated, @typescript-eslint/no-explicit-any | ||
| export const useARIAButtonShorthand: ResolveShorthandFunction<any> = ((value, options) => { |
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.
- why are we using
anyas generic ? - you can remove the explicit annotation as you are using assertion already
| export const useARIAButtonShorthand: ResolveShorthandFunction<any> = ((value, options) => { | |
| export const useARIAButtonShorthand = ((value, options) => { |

Previous Behavior
Slots API breaks on v18! 💣
ReactNode
The
ReactNodetype became more specific (there was a type leak onReactFragmenttype where{}was a valid type, and{}in typescript allows any of the primitive types butnullorundefinedmore info about this, here's a playground), and due to that specificity our declaration of what a slot is starts breaking on@types/react@18Here's a playground showcasing the error
RefAttributes
React.RefAttributesis therefproperty. In react v17 that would be equivalent to:Now in react v18 it became:
LegacyRefincludes the support to usestringas a valid reference value. This will break into our API 💣💣New Behavior
SlotPropsDataTypein favor ofUnknownSlotPropshttps://github.com/microsoft/fluentui/pull/31548/files#diff-06ee7aed2b4bc7589d4c744c7c6649fbee2ff0129915f344768e361a6cfb4dcdR5-R10UnknownSlotProps- its type is not equivalent to the actual signature of a slot. We do not have any restriction thatchildrenshould beReactNode | undefined,childrencan be any value. The only verification we have is if children is a function than its considered a render function, but we do not limit the children type in any way, in fact some of our components modifychildrensignature to be more specific like:fluentui/packages/react-components/react-field/src/components/Field/Field.types.ts
Line 63 in 5a8d7a2
fluentui/packages/react-components/react-utilities/src/trigger/types.ts
Line 28 in ee9ca8f
fluentui/packages/react-components/react-message-bar/src/components/MessageBarGroup/MessageBarGroup.types.ts
Line 12 in 40e6a37
fluentui/packages/react-components/react-popover/src/components/Popover/Popover.types.ts
Line 28 in 4cfa006
SlotShorthandValueto supportIterable<ReactNode>instead ofReactNode[](v18 modification)WithSlotRenderFunctionto properly include render function method (Fixes Can't use children render function in slots without Typescript errors #27090)WithoutSlotRenderFunctionSlotPropsDataTypedoes not have the requirement ofchildren?: ReactNodethe render function signature will leak, and this is a mistake in two scenarios:ComponentPropsshould not have a render functionSlotComponentTypeproperties should not have a render functionVoidFunctionComponentfromSlotgeneric signature (it is deprecated and redundant type, ComponentType covers the same use case)cloneTriggerTreeupdates signature to properly assume the possibility of more than justReactNodefromchildrenvalue.ForwardRefComponentandgetIntrinsicElementPropsupdates to stop usingReact.RefAttributes(in the v18 upgrade this type now supportLegacyRef, which we do not support)What are the Breaking Changes here?
UnknownSlotPropsand now depends onSlotPropsDataTypebecame less strictComponentPropsnow explicitly removes render function signatures from primary slot (this was already supposed to be like that, it's a bugfix IMO)ComponentStateexplicitly removes render function signatures to ensure things were as they we beforeTechnically, if the client is using
Slot,ComponentProps,ComponentState, anslot.*there'll be no breaking changes (as we are just moving verifications from one type to another) but if that is not the case then we could have some false positives due to the wider signature ofSlotPropsDataTypeRelated Issue(s)