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

useConfirm calls deprecated ReactDOM.render, triggering warning in React 18 #2990

Closed
iansan5653 opened this issue Mar 6, 2023 · 2 comments
Closed

Comments

@iansan5653
Copy link
Contributor

iansan5653 commented Mar 6, 2023

useConfirm uses ReactDOM.render to inject the confirmation dialog into the HTML.

ReactDOM.render(
<ThemeProvider {...themeProps}>
<ConfirmationDialog {...confirmationDialogProps} onClose={onClose}>
{content}
</ConfirmationDialog>
</ThemeProvider>,
hostElement,
)

This triggers a warning in the console when in development mode:

Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

While the warning states that the whole app will behave like it's running React 17, this isn't really the case - only the dialog will. This is because the call to render creates a whole new React app instance which only contains the dialog. However, this still isn't great and we definitely should resolve this.


The obvious solution is to just use createRoot instead, but it seems like there must be a more elegant alternative here than to create an entirely new React application. What if we could come up with a way to extract the Portal component into a usePortal hook, allowing rendering arbitary JSX into the default portal from any hook? Something like this:

function useConfirm() {
  const renderIntoPortal = usePortal()

  return () => new Promise(_resolve => {
    const resolve = (result) => {
      _resolve(result)
      renderIntoPortal(null)
    }
    renderIntoPortal(
      <ConfirmationDialog onClose={resolve(false)}>
        <Button onClick={resolve(true)}>Confirm</Button>
      </ConfirmationDialog>
    )
  })
}

I'm not sure if this is actually technically possible though - maybe I'll try and come up with a POC this week.

@mattcosta7
Copy link
Collaborator

One thing that might cause some interesting changes/need consideration

Synthetic Events are bound to the parent react root, so events from a portal'd element will bubble the react dom, where calling render like the confirm does now creates a new react root that events shouldn't (iirc) bubble the react root from (but can bubble the dom).

we would likely need a portal that blocks events from bubbling the react root in that case (which maybe portals should always optionally do)

@radglob
Copy link
Contributor

radglob commented Jul 20, 2023

Closed by #3367

@radglob radglob closed this as completed Jul 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants