Search code examples
reactjschakra-ui

ForwardRef error in Chakra-ui when wrapping IconButton component


I created a reusable component that wraps the IconButton and pass as one of the props icons from react-icons.

I get the following error:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?`

Here's my component wrapper:


export function SidebarMenu({ icon, isActive, handleMenuClick, name }) {
  return (
    <IconButton
      className={isActive ? 'active' : ''}
      aria-label={name + ' menu'}
      isActive={isActive}
      bg="transparent"
      px="0"
      as={icon}
      _hover={{
        cursor: 'pointer',
        backgroundColor: 'transparent',
      }}
      _active={{
        backgroundColor: 'transparent',
      }}
      onClick={() => handleMenuClick(name)}
    />

Here's how i use the wrapper component

   <SidebarMenu
    icon={VscCode}
    name="folders"
    handleMenuClick={handleMenuClick}
    isActive={menuList.folders}
   />

But if i change the content IconButton to a instead use a Icon wrapped in a Button the error disappears.

export function SidebarMenu({ icon, isActive, handleMenuClick, name }) {
  return (
    <Button
      className={isActive ? 'active' : ''}
      aria-label={name + ' menu'}
      isActive={isActive}
      bg="transparent"
      px="0"
      // as={icon}
      _hover={{
        cursor: 'pointer',
        backgroundColor: 'transparent',
      }}
      _active={{
        backgroundColor: 'transparent',
      }}
      onClick={() => handleMenuClick(name)}
    >
      <Icon as={icon} w={7} h={7} />
    </Button>
  );
}

Edit: For anyone who may stumble on the same problem. There are couple of things i did wrong here.

  1. I was using as instead of icon prop in IconButton
  2. Second, i was passing a reference instead of the component Instead of doing <IconButton icon={<VsColorMode />} />, i was doing this <IconButton icon={VsCodeMode} />.

Solution

  • According to the doc, IconButton has its own prop icon, so instead of using as, in this case, use icon with Icon

    function SidebarMenu({ icon }) {
      return (
        <IconButton
          bg="transparent"
          px="0"
          icon={<Icon as={icon} w={7} h={7} />}
          // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          _hover={{
            cursor: "pointer",
            backgroundColor: "transparent"
          }}
          _active={{
            backgroundColor: "transparent"
          }}
        />
      );
    }
    

    Codesandbox demo

    Edit laughing-rain-43jfhl