13

I have a Component that renders a Material UI MenuItem with icon and text:

export default class ProjectMenuItem extends Component {
  render() {
    return (
      <MenuItem onClick={this.props.onClick}>
        <ListItemIcon>{this.props.iconComponent}</ListItemIcon>
        <ListItemText primary={this.props.text} />
      </MenuItem>
    );
  }
}

This works fine. What I am struggling to understand is why I get a Warning: Function components cannot be given refs. Attempts to access this ref will fail. if I change this component to a functional component :

export const ProjectMenuItem = ({ onClick, iconComponent, text }) => {
  return (
    <MenuItem onClick={onClick}>
      <ListItemIcon>{iconComponent}</ListItemIcon>
      <ListItemText primary={text} />
    </MenuItem>
  );
};

The parent component:

      <StyledMenu
        id='customized-menu'
        anchorEl={anchorEl}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleClose}>
        {projectMenuItens.map((menuItem, i) => (
          <ProjectMenuItem
            key={i}
            onClick={menuItem.onClick}
            text={menuItem.text}
            iconComponent={menuItem.iconComponent}
          />
        ))}
      </StyledMenu>

The full warning is:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? Check the render method of ForwardRef(Menu).

Felipe V
  • 494
  • 2
  • 5
  • 16
  • check this https://github.com/mui-org/material-ui/issues/15903#issuecomment-496313450. It might solve your problem. – Gireesh Jun 29 '20 at 20:09

1 Answers1

18

The StyledMenu component tries to assign a ref to your ProjectMenuItem components. Refs cannot be used on function components because they don't have instances. You may only use them on class components or DOM elements.

If you want ProjectMenuItem to be a function component, use react's React.forwardRef utility:

export const ProjectMenuItem = React.forwardRef(({onClick, iconComponent, text}, ref) => (
    <MenuItem onClick={onClick} ref={ref}>
      <ListItemIcon>{iconComponent}</ListItemIcon>
      <ListItemText primary={text} />
    </MenuItem>
));

You can read more on refs in the official react docs.

Befeepilf
  • 617
  • 4
  • 10
  • 1
    Will it cause problems to ignore this error, if everything works as expected ? (might be related: [react-router, forwardRef API in withRouter](https://github.com/ReactTraining/react-router/issues/6056#issuecomment-435524678)) – kca May 07 '21 at 11:12
  • 1
    @kca The above message says "Warning" but not "Error" and is generated by React itself, so concerning React you won't get any runtime errors if you ignore this warning. However, other components which use the affected functional component as a child might rely on it accepting a ref, so make sure to read the docs and to examine the source code. – Befeepilf May 08 '21 at 17:29
  • 1
    This does not explain why that error is given for a class component. – paddotk Mar 03 '23 at 12:30