Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

material-ui v4.0.1 warning "Expected an element that can hold a ref"

I upgraded to material-ui v4.0.1 and I see that Modals now require a forwarded ref. I'm having some trouble implementing a fix for this using class components and Dialogs.

I tried using React.createRef() as well as React.forwardRef((props, ref) => (...) in a few places but I can't figure out how to resolve this warning.

In my parent component I render a custom component

<ApolloFormDialog />

In ApolloFormDialog I render essentially:

<Dialog ...>
  {title}
  {subtitle}
  {form}
</Dialog>

The full warning is Warning: Failed prop type: Invalid prop 'children' supplied to 'Modal'. Expected an element that can hold a ref. Did you accidentally use a plain function component for an element instead?

However I am using class components currently. Migrating to use function components is not an option right now as my app is rather large.


I have tried adding a ref to ApolloFormDialog as

<ApolloFormDialog ref={React.createRef()} />

as well as wrapping ApolloFormDialog's class with:

export default React.forwardRef((props, ref) => <ApolloFormDialog ref={ref} {...props}/>)

and then adding that ref to the dialog as

<Dialog ref={this.props.ref} />

but the warning still persists, and I'm not sure where to go from here.

like image 992
Lief Avatar asked May 28 '19 18:05

Lief


2 Answers

I have had the same problem with "@material-ui/core/Tooltip" wrapping a new functional component. Even if the component was wrapped in a div inside its own code.

<!-- "Did you accidentally use a plain function component for an element instead?" -->

<Tooltip>
  <NewFunctionalComponent />
</Tooltip>

<!-- Wrapped in a new div, devtools won't complain anymore -->

<Tooltip>
  <div>
    <NewFunctionalComponent />
  </div>
</Tooltip>

<!-- No more warnings! -->
like image 195
Thomas Zimmermann Avatar answered Oct 20 '22 10:10

Thomas Zimmermann


My issue didn't actually have to do with Dialog, but with the prop TransitionComponent on Dialog.

I switch between two types of transitions in my ApolloFormDialog depending on if the screen is below a certain breakpoint, which was being called as function components:

<Dialog
  open={open}
  onClose={onRequestClose}
  classes={{
    paper: classnames(classes.dialogWidth, classes.overflowVisible),
  }}
  fullScreen={fullScreen}
  TransitionComponent={
    fullScreen ? FullscreenTransition : DefaultTransition
  }
>
  {content}
</Dialog>

FullscreenTransition and DefaultTransition come from a file and are defined as follows:

import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export function DefaultTransition(props) {
  return <Fade {...props} />
}

export function FullscreenTransition(props) {
  return <Slide direction='left' {...props} />
}

export function FullscreenExpansion(props) {
  return <Slide direction='right' {...props} />
}

Changing these functions to the following fixed my issue:

import React from 'react'
import Fade from '@material-ui/core/Fade'
import Slide from '@material-ui/core/Slide'

export const DefaultTransition = React.forwardRef((props, ref) => (
  <Fade {...props} ref={ref} />
))

export const FullscreenTransition = React.forwardRef((props, ref) => (
  <Slide direction='left' {...props} ref={ref} />
))

export const FullscreenExpansion = React.forwardRef((props, ref) => (
  <Slide direction='right' {...props} ref={ref} />
))


This was a relatively hard issue to solve on my end, so I'm going to leave this question up just in case someone else runs into a similar issue somewhere down the road.

like image 26
Lief Avatar answered Oct 20 '22 10:10

Lief