Home > Mobile >  react.js: Invalid hook call
react.js: Invalid hook call

Time:05-05

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.

CodePudding user response:

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.

CodePudding user response:

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 />

  • Related