0

I am learning React by making a motor cycle spec searching web application, and I am trying to import fetched data into makePicker.jsx to essentially make a drop down menu with those data.

However I am getting an error message saying:

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

I am not sure what applies to my situation. Can you see why?

makePicker.jsx

import React, {useState, useEffect} from 'react';
import {NativeSelect, FormControl} from '@material-ui/core';
import styles from './makePicker.module.css';
import { makeList } from '../../api';

const MakePicker = ()=>{

  const [fetchedMakes, setFetchedMakes] = useState([]);

  useEffect(()=>{
    const fetchAPI = async()=>{
      setFetchedMakes(await makeList());
    }
    fetchAPI();
  },[])

  return (
    <h1>makePicker</h1>
  );

}

export default MakePicker;

App.js

import logo from './logo.svg';
import './App.css';
import {fetchData, makeList} from './api/index';
import React, {Component} from 'react';
import MakePicker from './components/makePicker/makePicker';

class App extends React.Component{
  state = {

    data:[],
    makes:[],
  }

  async componentDidMount(){
//    const fetchedData = await fetchData();
    const fetchedMakeList = await makeList();
    this.setState({makes:fetchedMakeList});
  
    
  }


render(){
  
  return (
    <div className="App">
      <header className="App-header">
      {MakePicker()};
      <h1>Some line-ups from YAMAHA</h1>
      {this.state.makes.map(make=>{
        return <p>{make.name}</p>
      })}
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Open React
        </a>
      </header>
    </div>
  );
}

}
  
export default App;


Please let me know if need more information from my project.

Hayato
  • 61
  • 1
  • 6
  • 5
    The code provided does not throw that error. – evolutionxbox May 05 '22 at 08:29
  • How did you call `MakePicker` in another component? – Nick Vu May 05 '22 at 08:29
  • I agree with the commenters above: we need to see the other files because this code won't produce any hooks errors. Just guessing: are you using hooks in your API route? Because that will throw an error – James Hooper May 05 '22 at 08:51
  • This happens when you use Hooks outside jsx component. This answer can be useful https://stackoverflow.com/questions/62077729/is-it-possible-to-use-react-hooks-outside-of-functional-component-or-i-have-to – Levi D. May 05 '22 at 08:57
  • `MakePicker` is a component; not the function. So instead of `{MakePicker()};` define as JSX element i.e. `` – user1672994 May 05 '22 at 09:01

2 Answers2

2

According to your code in App.jsx and following the naming convention of React's component, you should import it with the first-capitalized-letter name like below

import MakePicker from './components/makePicker/makePicker';

You're also calling {makePicker()}; which is not a proper way for component rendering. You should modify it to

<MakePicker/>

Full possible change can be

import logo from './logo.svg';
import './App.css';
import {fetchData, makeList} from './api/index';
import React, {Component} from 'react';
import MakePicker from './components/makePicker/makePicker';

class App extends React.Component{
  state = {

    data:[],
    makes:[],
  }

  async componentDidMount(){
//    const fetchedData = await fetchData();
    const fetchedMakeList = await makeList();
    this.setState({makes:fetchedMakeList});
  
    
  }


render(){
  
  return (
    <div className="App">
      <header className="App-header">
      <MakePicker/>
      <h1>Some line-ups from YAMAHA</h1>
      {this.state.makes.map(make=>{
        return <p>{make.name}</p>
      })}
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Open React
        </a>
      </header>
    </div>
  );
}

}
  
export default App;

To elaborate more why you get this error

Invalid hook call. Hooks can only be called inside of the body of a function component.

When you call makePicker(), it's actually triggering a Javascript's function (not React's component as you expected), but useEffect is only available in React's components. That's why when you try to run code, the compiler is thinking makePicker is calling useEffect invalidly.

Nick Vu
  • 14,512
  • 4
  • 21
  • 31
1

Their is a problem lies on your useEffect

update the code like this and try it out:

 const fetchAPI = async()=>{
      const res = await makeList().then((data) => {
          setFetchedMakes(data)
       }).catch((err) => console.log(err))

 }
 useEffect(()=>{
    fetchAPI();
  },[])

here i placed the asynchronous function outside of the useEffect

Also make MakePicker as an JSX element like this: <MakePicker />

Rahman Haroon
  • 1,088
  • 2
  • 12
  • 36