Check the render method of ForwardRef

Viewed 4958

I use exactly the code as defined in the example from https://material-ui.com/components/bottom-navigation/:

// saved in app.tsx:

import React from 'react';

import { makeStyles } from '@material-ui/core/styles';
import BottomNavigation from '@material-ui/core/BottomNavigation';
import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
import FolderIcon from '@material-ui/icons/Folder';
import RestoreIcon from '@material-ui/icons/Restore';
import FavoriteIcon from '@material-ui/icons/Favorite';
import LocationOnIcon from '@material-ui/icons/LocationOn';

const useStyles = makeStyles({
  root: {
    width: 500,
  },
});


export default function LabelBottomNavigation() {
  const classes = useStyles();
  const [value, setValue] = React.useState('recents');

  const handleChange = (event: React.ChangeEvent<{}>, newValue: string) => {
    setValue(newValue);
  };

  return (
    <BottomNavigation value={value} onChange={handleChange} className={classes.root}>
      <BottomNavigationAction label="Recents" value="recents" icon={<RestoreIcon />} />
      <BottomNavigationAction label="Favorites" value="favorites" icon={<FavoriteIcon />} />
      <BottomNavigationAction label="Nearby" value="nearby" icon={<LocationOnIcon />} />
      <BottomNavigationAction label="Folder" value="folder" icon={<FolderIcon />} />
    </BottomNavigation>
  );
}

However when using this component in index.tsx:

// saved in index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App/>
  </React.StrictMode>,
  document.getElementById('root'),
);

I get this error:

Unhandled Runtime Error

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of `ForwardRef(BottomNavigationAction)`.

My package.json:

{
  "scripts": {
    "start": "snowpack dev",
    "build": "snowpack build",
    "test": "web-test-runner \"src/**/*.test.tsx\"",
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
    "lint": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\""
  },
  "dependencies": {
    "@material-ui/core": "^4.11.3",
    "@material-ui/icons": "^4.11.2",
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  },
  "devDependencies": {
    "@snowpack/plugin-dotenv": "^2.0.5",
    "@snowpack/plugin-react-refresh": "^2.4.0",
    "@snowpack/plugin-typescript": "^1.2.0",
    "@snowpack/web-test-runner-plugin": "^0.2.0",
    "@testing-library/react": "^11.0.0",
    "@types/chai": "^4.2.13",
    "@types/mocha": "^8.2.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "@types/snowpack-env": "^2.3.2",
    "@web/test-runner": "^0.12.0",
    "chai": "^4.2.0",
    "css-loader": "^5.2.0",
    "prettier": "^2.0.5",
    "snowpack": "^3.0.1",
    "ts-loader": "^8.1.0",
    "typescript": "^4.0.0"
  }
}

What is the reason for this error and how can I solve it?

3 Answers

this is because using <React.StrictMode> remove <React.StrictMode> and try again

// saved in index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <App/>,
  document.getElementById('root'),
);

demo

The crucial part of the error is not the part **Check the render method of ForwardRef(BottomNavigationAction). **. This only tells you where to look for the error.

The important part of the error is:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

This usually happens when you don't pass a React component in the right way. I often faced this error when passing icon components in the wrong way.

For example instead of icon={<RestoreIcon />}, I would pass icon={RestoreIcon}. However, you seem to be passing the icons in the right manner.

The icon has to be a so-called ReactNode. It's Typescript type is:

type ReactNode = ReactElement | string | number | ReactFragment | ReactPortal | boolean | null | undefined;

So when getting passed an object it will through an error.

I share different ways in which you could pass a component:

  • icon={<RestoreIcon />}
  • icon={RestoreIcon}
  • icon={RestoreIcon()} will complain about missing props argument
  • icon={props => <RestoreIcon {...props} />}

I don't know why. But try this:

import {
  BottomNavigation
  // your other import here
} from '@material-ui/core'
Related