Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Warning: Function components cannot be given refs

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).

like image 576
Felipe V Avatar asked Jun 29 '20 19:06

Felipe V


1 Answers

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.

like image 125
Befeepilf Avatar answered Oct 11 '22 19:10

Befeepilf