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

React 19 element.ref access warning in ComboboxEventsTarget #7028

Closed
2 tasks done
Pirulax opened this issue Oct 24, 2024 · 9 comments
Closed
2 tasks done

React 19 element.ref access warning in ComboboxEventsTarget #7028

Pirulax opened this issue Oct 24, 2024 · 9 comments
Labels
Fixed patch Completed issues that will be published with next patch (1.0.X)

Comments

@Pirulax
Copy link

Pirulax commented Oct 24, 2024

Dependencies check up

  • I have verified that I use latest version of all @mantine/* packages

What version of @mantine/* packages do you have in package.json?

^7.13.4

What package has an issue?

@mantine/core

What framework do you use?

Next.js

In which browsers you can reproduce the issue?

Not applicable – issue is not related to the browser

Describe the bug

I get the following error in my console:

Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.

Call Stack
ConsoleError: Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.
    at handleClientError (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:794:17)
    at window.console.error (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:893:56)
    at console.error (http://localhost:3000/_next/static/chunks/node_modules_4596ad._.js:18213:13)
    at Object.elementRefGetterWithDeprecationWarning (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_107ce8._.js:2185:103)
    at @mantine/core/ComboboxEventsTarget (http://localhost:3000/_next/static/chunks/node_modules_aa26a4._.js:10965:265)
    at react-stack-bottom-frame (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:12381:24)
    at renderWithHooks (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:3396:24)
    at updateForwardRef (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:4626:21)
    at beginWork (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:5408:24)
    at runWithFiberInDEV (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:631:20)
    at performUnitOfWork (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7930:97)
    at workLoopSync (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7823:40)
    at renderRootSync (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7806:13)
    at performWorkOnRoot (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7547:175)
    at performSyncWorkOnRoot (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8387:9)
    at flushSyncWorkAcrossRoots_impl (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8316:245)
    at processRootScheduleInMicrotask (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8333:9)
    at http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8398:126

And also the following:

Cannot update a component (HotReload) while rendering a different component (@mantine/core/ComboboxEventsTarget). To locate the bad setState() call inside @mantine/core/ComboboxEventsTarget, follow the stack trace as described in https://react.dev/link/setstate-in-render

Call Stack
ConsoleError: Cannot update a component (`HotReload`) while rendering a different component (`@mantine/core/ComboboxEventsTarget`). To locate the bad setState() call inside `@mantine/core/ComboboxEventsTarget`, follow the stack trace as described in https://react.dev/link/setstate-in-render
    at handleClientError (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:794:17)
    at window.console.error (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:893:56)
    at console.error (http://localhost:3000/_next/static/chunks/node_modules_4596ad._.js:18213:13)
    at scheduleUpdateOnFiber (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7538:201)
    at dispatchReducerAction (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:4324:199)
    at http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:12194:9
    at handleClientError (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:802:9)
    at window.console.error (http://localhost:3000/_next/static/chunks/node_modules_next_dist_client_23b1be._.js:893:56)
    at console.error (http://localhost:3000/_next/static/chunks/node_modules_4596ad._.js:18213:13)
    at Object.elementRefGetterWithDeprecationWarning (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_107ce8._.js:2185:103)
    at @mantine/core/ComboboxEventsTarget (http://localhost:3000/_next/static/chunks/node_modules_aa26a4._.js:10965:265)
    at react-stack-bottom-frame (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:12381:24)
    at renderWithHooks (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:3396:24)
    at updateForwardRef (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:4626:21)
    at beginWork (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:5408:24)
    at runWithFiberInDEV (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:631:20)
    at performUnitOfWork (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7930:97)
    at workLoopSync (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7823:40)
    at renderRootSync (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7806:13)
    at performWorkOnRoot (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:7547:175)
    at performSyncWorkOnRoot (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8387:9)
    at flushSyncWorkAcrossRoots_impl (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8316:245)
    at processRootScheduleInMicrotask (http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8333:9)
    at http://localhost:3000/_next/static/chunks/node_modules_next_dist_compiled_react-dom_1f56dc._.js:8398:126

Interestingly enough, using the same component in a modal (that is opened manually) doesn't cause any issues.
But if the same form is part of a page directly these errors pop up.
Let me know if you need any more info/code.

If possible, include a link to a codesandbox with a minimal reproduction

I'm pretty sure this happens on all React 19 builds, hence I don't think there's a need for a sandbox.
But, I can make one if necessary.

Possible fix

I'm not an expert, but I think I see what the fix would be.
I did a google-fu, and found this:

import * as React from 'react';

export default function getChildRef(child) {
  if (!child || !React.isValidElement(child)) {
    return null;
  }
  // 'ref' is passed as prop in React 19, whereas 'ref' is directly attached to children in React 18
  // below check is to ensure 'ref' is accessible in both cases
  return child.props.propertyIsEnumerable('ref') ? child.props.ref : child.ref;
}

material-ui commit (Scroll to the bottom)

Perhaps the same fix could be implemented here? (I assume this is the line causing the issue?)

[refProp!]: useMergedRef(ref, ctx.store.targetRef, (children as any)?.ref),

I'm willing to fix this issue with some guidance.
Thank you!

Self-service

  • I would be willing to implement a fix for this issue
@yorkeJohn
Copy link
Contributor

Note that this is also happening for popovers:

Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.

Cannot update a component (`HotReload`) while rendering a different component (`@mantine/core/PopoverTarget`). To locate the bad setState() call inside `@mantine/core/PopoverTarget`, follow the stack trace as described in https://react.dev/link/setstate-in-render

@enchorb
Copy link

enchorb commented Nov 1, 2024

Also occurring for the @mantine/core/Tooltip component which is also affecting positioning

@uncomplexity
Copy link

found this in discussions https://github.com/orgs/mantinedev/discussions/6323

i assum it's not advisable yet to upgrade to react 19?

@rtivital
Copy link
Member

rtivital commented Nov 3, 2024

React 19 has not been released yet, the latest available version of react on npm is 18.3.1. If you want to use experimental features, you can expect issues like this.

Once React 19 is out, these issues will be resolved in patch versions.

@icflorescu
Copy link
Contributor

@rtivital, I wish Vercel would share your opinion... 😊

If you're using the App Router in Next.js 15, which is now GA, they're forcing React 19 RC no matter what you're specifying in your package.json. And lots of people are choosing to start greenfield projects with Next.js 15 because they've finally fixed the aggressive caching. I've been working on a new project with Mantine and Next.js 15 for over three weeks now and had no real issues with it until I bumped into this while trying to use a <TagsInput />.

That being said, I may be wrong, but I think this would be quite easy to fix and a quick-win.
And I think @Pirulax is spot on.

Going through the codebase I've discovered just 4 places that trigger this error:

[refProp!]: useMergedRef(ref, ctx.store.targetRef, (children as any)?.ref),

const targetRef = useMergedRef(ctx.reference, (children as any).ref, ref);

const targetRef = useMergedRef(tooltip.reference, (children as any).ref, ref);

const targetRef = useMergedRef(boundaryRef, (children as any).ref, ref);

A quick, non-invasive way to have this fixed in the next patch version would be to simply replace (children as any).ref with (children as any).props?.ref || (children as any)?.ref.

Please let me know your thoughts.
I can come up with a PR if you agree with the idea.

@rtivital
Copy link
Member

rtivital commented Nov 4, 2024

(children as any).props?.ref || (children as any)?.ref I doubt that this will solve the issue. (children as any).props?.ref is in most cases will be undefined and it will go to (children as any)?.ref. I will explore this issue in more details once React 19 is out. Currently, I do not see any reason to rush things.

@icflorescu
Copy link
Contributor

icflorescu commented Nov 4, 2024

@rtivital

Currently, I do not see any reason to rush things.

Like I said, if you're on Next.js 15 with the app router, it will always use its internally packaged React 19, no matter what you package.json says. Here's a screenshot of the simple Mantine Next.js template with a <TagsInput /> added:

Mantine with Next.js 15

Notice how the component inspector mentions "rendered by [email protected]".

AFAIK, there's simply no way to make it use React 18.
Not everyone is yet aware of that, as Vercel's docs are a bit murky and don't say this clearly, but that's how things are.

Which basically means anyone starting a new app with Next.js + Mantine will eventually bump into these issues.

It's just a matter of days till this will start to generate a lot of community pressure; I know what it means and I find it kind of frustrating too, because I'm also struggling to maintain Mantine DataTable and ContextMenu in my own spare time 😮‍💨

rtivital added a commit that referenced this issue Nov 8, 2024
…p usage in Tooltip, Popover and Combobox components (#7028)
@rtivital rtivital added the Fixed patch Completed issues that will be published with next patch (1.0.X) label Nov 8, 2024
@rtivital
Copy link
Member

rtivital commented Nov 8, 2024

As I predicted, the above approach does not work for React 18.3, it shows error. Instead, I've created a function that is now exported from @mantine/core package:

import React from 'react';

export function getRefProp(element: any) {
  const version = React.version;

  if (typeof React.version !== 'string') {
    return (element as any)?.ref;
  }

  if (version.startsWith('18.')) {
    return (element as any)?.ref;
  }

  return (element as any)?.props?.ref;
}

@rtivital
Copy link
Member

rtivital commented Nov 8, 2024

Fixed in 7.13.5

@rtivital rtivital closed this as completed Nov 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fixed patch Completed issues that will be published with next patch (1.0.X)
Projects
None yet
Development

No branches or pull requests

6 participants