1

In Review components, I want to use hooks and got error below.
In fact I use YhSection to manage my parallel components, and use array map to put them in layout content.
I find if I use hooks out of

{yhSection.map((section) => (
    <Route key={section.key} path={section.path}>
      {section.components}
    </Route>
))}

, it works, but in , it doesn't.
hooks call error is in Review.tsx

I'll really appreciate your help.


Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

MyContentWithRoute.tsx

import React, { FC } from 'react';
import { Route, Switch } from 'react-router-dom';
import { Layout } from 'antd';
import My404 from './My404';

import yhSection from './YhSection';

const MyContentWithRoute: FC = () => (
  <Layout.Content style={{ margin: '16px', background: '#fff' }}>
    <Switch>
      {yhSection.map((section) => (
        <Route key={section.key} path={section.path}>
          {section.components}
        </Route>
      ))}
      <Route path="*">
        <My404 />
      </Route>
    </Switch>
  </Layout.Content>
);

export default MyContentWithRoute;

YhSection.tsx

import { FC } from 'react';

import Review from './Review';
import Profit from './Profit';
import Policy from './Policy';
import Fluid from './Fluid';
import Capital from './Capital';
import Risk from './Risk';
import Trader from './Trader';
import Valuation from './Valuation';

interface YhSection {
  key: string;
  name: string;
  path: string;
  components: FC;
}

const yhSection: YhSection[] = [
  { key: 'review', path: '/review', components: Review },
  { key: 'profit', path: '/profit', components: Profit },
  { key: 'policy', path: '/policy', components: Policy },
  { key: 'fluid', path: '/fluid', components: Fluid },
  { key: 'capital', path: '/capital', components: Capital },
  { key: 'risk', path: '/risk', components: Risk },
  { key: 'trader', path: '/trader', components: Trader },
  { key: 'valuation', path: '/valuation', components: Valuation },
];

export default yhSection;

Review.tsx

import React, { useState } from 'react';
import Chart from './Chart';

const Review: React.FC = () => {
  const [state, setState] = useState(2);
  const data1 = [
    { date: '1991', value: 3 },
    { date: '1992', value: 4 },
    { date: '1993', value: 3.5 },
    { date: '1994', value: 5 },
    { date: '1995', value: 4.9 },
    { date: '1996', value: 6 },
    { date: '1997', value: 7 },
    { date: '1998', value: 9 },
    { date: '1999', value: 13 },
  ];
  console.log(state);
  return <Chart data={data1} />;
};

export default Review;

package.json

{
  "name": "vmp_frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@ant-design/charts": "^0.9.6",
    "@craco/craco": "^5.6.4",
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "@types/jest": "^24.9.1",
    "@types/node": "^12.12.47",
    "@types/react": "^16.9.36",
    "@types/react-dom": "^16.9.8",
    "@types/react-router-dom": "^5.1.5",
    "ahooks": "^2.0.1",
    "antd": "^4.3.4",
    "axios": "^0.19.2",
    "craco-less": "^1.17.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "3.4.1",
    "typescript": "^3.7.5"
  },
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "craco eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^3.3.0",
    "@typescript-eslint/parser": "^3.3.0",
    "eslint": "^6.8.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-react": "^7.20.0",
    "eslint-plugin-react-hooks": "^4.0.4",
    "prettier": "^2.0.5"
  }
}

4
  • Its probably because of mismatching in version between types and packages. You should use "@types/react": "^16.13.1", "@types/react-dom": "^16.13.1", "@types/react-router-dom": "^5.2.0", for versions Commented Jul 1, 2020 at 5:38
  • In fact, I test use hooks out of that map, It works. So I guess version is OK Commented Jul 1, 2020 at 5:43
  • Is this error still thrown if you put the Review component out of MyContentWithRoute? For example, put it directly under the root component (App?). This way you could find out if the problem is with the Review component or the integration with the Routes Commented Jul 1, 2020 at 5:57
  • if I put the Review component out of MyContentWithRoute, it works. Even if I use route like ``` <Layout.Content style={{ margin: '16px', background: '#fff' }}> <Switch> <Route key={'review'} path={'./review'}> <Review> </Route> <Route path="*"> <My404 /> </Route> </Switch> </Layout.Content> ``` it works too, So I think it might caused by map instead of route Commented Jul 1, 2020 at 5:59

2 Answers 2

3

It seems that you are trying to render a component function instead of component JSX instance. Just look at this:

{ key: 'review', path: '/review', components: Review }, // here Review is component function
{yhSection.map((section) => (
    <Route key={section.key} path={section.path}>
      {/* here it is still a component function not a JSX element (it is Review and not <Review /> or React.createElement(Review) */}
      {section.components}
    </Route>
))}

Try to pass the component function directly into Route as parameter:

{yhSection.map((section) => (
  <Route key={section.key} path={section.path} component={section.components} />
))}
Sign up to request clarification or add additional context in comments.

1 Comment

it works! Thank u so much for your patient explanation, this helps me a lot
1

Try the following

<Route 
  key={section.key}
  path={section.path}
  component={section.components} 
/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.