Skip to content

[Bug]: Slots API types do not work correctly in React 18 #31482

Closed as not planned
@sopranopillow

Description

@sopranopillow

Library

React Components / v9 (@fluentui/react-components)

System Info

React 18
@fluentui/react-components@latest

Are you reporting Accessibility issue?

no

Reproduction

https://stackblitz.com/edit/vitejs-vite-gek5ur?file=src%2FTest.ts

Bug Description

The type above is React 17 and the one below is React 18:

    // 17
    type ReactFragment = {} | Iterable<ReactNode>;
    type ReactChild = Reactlement | ReactText;
    type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

    // 18
    type ReactNode =
        | ReactElement
        | string
        | number
        | Iterable<ReactNode>
        | ReactPortal
        | boolean
        | null
        | undefined
        | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[
            keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES
        ];

The error shows the following:

image

which further inspecting, the problem is not really where we thought. The problem comes from here:

image

Where we are checking that the provided slots follow the SlotPropsRecord type, this is where we get errors. So poking further takes us here

image

input is of type intrinsic slot therefore follows UnknownSlotProps and this is where things go south:

image

We are getting the children from HTMLAttributes but with the React 18 update there were breaking changes to this and as outlined at the beginning ReactNode clashes due to ReactElement being different. which makes sense based on the error we are getting:

image

What I would propose is to have stricter types for children, I've tested this and the following update and works correctly. While ideally we would prefer to keep using what we have, this breaking change in React 18 will sadly stop us from doing so :/ One thing to note is that I would say we should be careful adding this to our types, if we decide to move back to relying on HTMLAttributes we will be introducing a breaking change, so this could possibly more of a "shim" for react 18 like Justin mentioned.

Finally, here's the update I mentioned that worked:

// our current types
export declare type UnknownSlotProps = Pick<React_2.HTMLAttributes<HTMLElement>, 'children' | 'className' | 'style'> & {
    as?: keyof JSX.IntrinsicElements;
};

// proposed change, notice this is what R17 resolves to, so we are just making sure it receives the expected type
export declare type UnknownSlotProps = Pick<Omit<React_2.HTMLAttributes<HTMLElement>, 'children'>, 'className' | 'style'> & {
    as?: keyof JSX.IntrinsicElements;
    children?:ReactChild | React.ReactFragment | React.ReactPortal | boolean;
};

Logs

No response

Requested priority

Blocking

Products/sites affected

OOUI

Are you willing to submit a PR to fix?

yes

Validations

  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • The provided reproduction is a minimal reproducible example of the bug.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions