Skip to content

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

Closed
@iansan5653

Description

@iansan5653

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions