Skip to content
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

[core] React 19 compatibility #605

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

michaldudak
Copy link
Member

@michaldudak michaldudak commented Sep 12, 2024

Work in progress to ensure Base UI is compatible with React 19.

After this is approved, I'll revert all the changes to package.json files, and, if the checks are green, merge it into master.

@michaldudak michaldudak added the core Infrastructure work going on behind the scenes label Sep 12, 2024
@mui-bot
Copy link

mui-bot commented Sep 12, 2024

Netlify deploy preview

https://deploy-preview-605--base-ui.netlify.app/

Generated by 🚫 dangerJS against e1403e9

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 14, 2024
@oliviertassinari oliviertassinari added the React 19 support PRs required to support React 19 label Sep 15, 2024
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Connecting the dots with the other projects: Aaron went through a lot of those changes mui/material-ui#42824. I think it would be great to have his review.

docs/src/blocks/GoogleAnalytics.tsx Outdated Show resolved Hide resolved
docs/src/components/GoogleAnalytics.tsx Outdated Show resolved Hide resolved
) => JSX.Element;
) => React.JSX.Element;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 to bring this to the main branch

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I intend to have everything (except for package.json changes) merged to master.

@@ -79,7 +79,7 @@ export function useComponentRenderer<

let resolvedRenderProp:
| ComponentRenderFn<React.HTMLAttributes<any>, OwnerState>
| React.ReactElement;
| React.ReactElement<any>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

? mui/material-ui#43402

Suggested change
| React.ReactElement<any>;
| React.ReactElement<unknown>;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't really care about the shape of the props here, especially that it's an internal hook and its type shouldn't be publicly visible. To constrain it a bit more, I changed it to Record<string, unknown>

Comment on lines 14 to 19
let childRef;
if (isReactVersionAtLeast(19)) {
childRef = typeof render !== 'function' ? render.props.ref : null;
} else {
childRef = typeof render !== 'function' ? render.ref : null;
}
Copy link
Member

@oliviertassinari oliviertassinari Sep 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better fork after the typeof.

I'm sure this is best: mui/material-ui#42818 (comment). The explore we are exploring in mui/material-ui#43022. To decide then use the same solution through the codebase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better fork after the typeof

You mean const childRef = typeof render !== 'function' ? isReactVersionAtLeast(19) ? render.props.ref : render.ref : null;? This makes it a nested ternary which I believe we disallow in our ESLint rules.

I'm sure this is best: mui/material-ui#42818 (comment).

How do you measure "best"? The version check is faster than property check (https://jsbench.me/mrm16egz7n/1) and the function call explains pretty well that we're branching because something changed in React version.

Copy link
Member

@oliviertassinari oliviertassinari Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaldudak I was proposing to go from:

  let childRef;
  if (isReactVersionAtLeast(19)) {
    childRef = typeof render !== 'function' ? render.props.ref : null;
  } else {
    childRef = typeof render !== 'function' ? render.ref : null;
  }

to:

  let childRef;
  if (typeof render !== 'function') {
    childRef = isReactVersionAtLeast(19) ? render.props.ref : render.ref;
  } else {
    childRef = null;
  }

something we can later convert to:

  let childRef;
  if (typeof render !== 'function') {
    childRef = getReactElementRef(render);
  } else {
    childRef = null;
  }

How do you measure "best"?

To be defined 😄. We had another iteration in mui/material-ui#43022 with @sai6855. I could see the purpose of going with the React version check. I don't see one path as clearly better than the other, so happy either way.

The only ask is that we are moving to a place where Base UI is exporting one helper and Material UI, etc. using it. I don't think that this should be duplicated.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was proposing to go...

All right, makes sense 👍

The only ask is that we are moving to a place where Base UI is exporting one helper and Material UI, etc. using it. I don't think that this should be duplicated.

I see your point. I don't feel comfortable sharing Base UI utils just yet, though, even internally. When we're closer to the release and breaking changes are less likely, we can review the whole codebase and move utilities where they ultimately belong.

Copy link
Member

@oliviertassinari oliviertassinari Sep 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel comfortable sharing Base UI utils just yet, though, even internally

This doesn't go in opposition with the ask 👍. We could duplicate the code of the helper until this happens (e.g. we have done this in MUI X mui/mui-x#14528 we had the same warnOnce() helper duplicated between packages). The outcome I'm trying to go after is: learn once, fix everywhere once. If one is better than the other, there is no reason for one project to do it differently than the other. If the difference is marginal, we are much better serviced using the same approach, so we can move everything at once when we learn more about the limits.

packages/mui-base/src/utils/useAnchorPositioning.ts Outdated Show resolved Hide resolved
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 17, 2024
@@ -7,7 +7,7 @@ import { styled } from '@mui/system';
export default function UnstyledTooltipFollowCursor() {
return (
<div style={{ display: 'flex', gap: 12 }}>
<Tooltip.Root followCursorAxis="both">
<Tooltip.Root trackCursorAxis="both">
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me why it started to fail now, but I guess it's a good thing it fails.

@@ -23,7 +23,7 @@ describe('<Field.Validity />', () => {
fireEvent.change(input, { target: { value: 'test' } });
fireEvent.blur(input);

const [data] = handleValidity.args[8];
const [data] = handleValidity.lastCall.args;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atomiks, could you please verify that with these changes the intent of these checks is the same?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's fine

@michaldudak michaldudak marked this pull request as ready for review September 17, 2024 20:54
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 18, 2024
@github-actions github-actions bot added PR: out-of-date The pull request has merge conflicts and can't be merged and removed PR: out-of-date The pull request has merge conflicts and can't be merged labels Sep 18, 2024
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Infrastructure work going on behind the scenes React 19 support PRs required to support React 19
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants