Bi-HanNoobSaibot
Bi-HanNoobSaibot

Reputation: 215

A weird error occurring when trying to implement useEffect

I am trying to use useEffect inside of my cockpit function that returns a couple of elements, but I get this weird error saying that "Line 6: React Hook "useEffect" is called in function "cockpit" which is neither a React function component or a custom React Hook function react-hooks/rules-of-hooks".

But surely my cockpit component is a function?

import React, { useEffect } from 'react'

import classes from './Cockpit.css'

const cockpit = (props) => {
  useEffect(() => {
    console.log('I work!')
  })

  const assignedClasses = []
  let btnClass = ''
  if (props.showPersons) {
    btnClass = classes.Red;
  }

  if (props.persons.length <= 2) {
    assignedClasses.push(classes.red)
  }
  if (props.persons.length <= 1) {
    assignedClasses.push(classes.bold)
  }

  return (
    <div className={classes.Cockpit}>
      <h1>{props.title}</h1>
      <p className={assignedClasses.join(' ')}>HELLO, HELLO!</p>
      <button
        className={btnClass}
        onClick={props.clicked}>Click me!</button>
    </div>
  )
}


export default cockpit

Upvotes: 17

Views: 5419

Answers (5)

Kamil Ghori
Kamil Ghori

Reputation: 1

import React, { useEffect, useRef, useContext } from 'react';
import classes from './Cockpit.css';
import AuthContext from '../../context/auth-context';

const Cockpit = props => {
  const toggleBtnRef = useRef(null);
  const authContext = useContext(AuthContext);

  console.log(authContext.authenticated);

  useEffect(() => {
    console.log('[Cockpit.js] useEffect');
    // Http request...
    // setTimeout(() => {
    //   alert('Saved data to cloud!');
    // }, 1000);
    toggleBtnRef.current.click();
    return () => {
      console.log('[Cockpit.js] cleanup work in useEffect');
    };
  }, []);

  useEffect(() => {
    console.log('[Cockpit.js] 2nd useEffect');
    return () => {
      console.log('[Cockpit.js] cleanup work in 2nd useEffect');
    };
  });

  // useEffect();

  const assignedClasses = [];
  let btnClass = '';
  if (props.showPersons) {
    btnClass = classes.Red;
  }

  if (props.personsLength <= 2) {
    assignedClasses.push(classes.red); // classes = ['red']
  }
  if (props.personsLength <= 1) {
    assignedClasses.push(classes.bold); // classes = ['red', 'bold']
  }

  return (
    <div className={classes.Cockpit}>
      <h1>{props.title}</h1>
      <p className={assignedClasses.join(' ')}>This is really working!</p>
      <button ref={toggleBtnRef} className={btnClass} onClick={props.clicked}>
        Toggle Persons
      </button><hr/>
      <button onClick={authContext.login}>Log in</button>
    
    </div>
  );
};

export default React.memo(Cockpit);

simply remove your cockpit component code and copy which i have give in this answer

Upvotes: 0

Mehedi Hasan Shifat
Mehedi Hasan Shifat

Reputation: 720

According to react doc User-Defined Components Must Be Capitalized !

In case if you are using only react then you can define your component function name starting with small letter but have you noticed that when you are using the component in rendering you are using it as import Cockpit from './bla bla' . So If you do have a component that starts with a lowercase letter, assign it to a capitalized variable before using it in JSX.

But if you are using hook with react in that component then your Components have to be capitalized. I have also seen the Udemy course . That guy was okey with cocktail named component but i think it was related to the version of react and hook !

Again i have noticed that you are using css modules . Did you set config for using css module as the course ?? I must mention that you can use css module without running 'npm run eject' and these complicated config as React 2 support css modules you just need to change the extension from .css to .module.css

Here is the clean code for your :

import React, { useEffect } from 'react'

import classes from './Cockpit.module.css'

const Cockpit = (props) => {
  useEffect(() => {
    console.log('I work!')
  })

  const assignedClasses = []
  let btnClass = ''
  if (props.showPersons) {
    btnClass = classes.Red;
  }

  if (props.persons.length <= 2) {
    assignedClasses.push(classes.red)
  }
  if (props.persons.length <= 1) {
    assignedClasses.push(classes.bold)
  }

  return (
    <div className={classes.Cockpit}>
      <h1>{props.title}</h1>
      <p className={assignedClasses.join(' ')}>HELLO, HELLO!</p>
      <button
        className={btnClass}
        onClick={props.clicked}>Click me!</button>
    </div>
  )
}


export default Cockpit

Upvotes: 3

Rajesh M
Rajesh M

Reputation: 21

I also ran into same problem and was able to resolve by uppercasing the component name. I don't know how the udemy instructor's code works without that change. Attaching his screenshot.enter image description here

Upvotes: 0

Shivam Lakhwara
Shivam Lakhwara

Reputation: 29

//This is the exact solution

import React, { useEffect } from 'react';

import classes from './Cockpit.css';

const Cockpit = props => {
  useEffect(() => {
    console.log('[Cockpit.js] useEffect');
    // Http request...
    setTimeout(() => {
      alert('Saved data to cloud!');
    }, 1000);
    return () => {
      console.log('[Cockpit.js] cleanup work in useEffect');
    };
  }, []);

  useEffect(() => {
    console.log('[Cockpit.js] 2nd useEffect');
    return () => {
      console.log('[Cockpit.js] cleanup work in 2nd useEffect');
    };
  });

  // useEffect();

  const assignedClasses = [];
  let btnClass = '';
  if (props.showPersons) {
    btnClass = classes.Red;
  }

  if (props.persons.length <= 2) {
    assignedClasses.push(classes.red); // classes = ['red']
  }
  if (props.persons.length <= 1) {
    assignedClasses.push(classes.bold); // classes = ['red', 'bold']
  }

  return (
    <div className={classes.Cockpit}>
      <h1>{props.title}</h1>
      <p className={assignedClasses.join(' ')}>This is really working!</p>
      <button className={btnClass} onClick={props.clicked}>
        Toggle Persons
      </button>
    </div>
  );
};

export default Cockpit;

// Look out for the identifier names of the const and the export

Upvotes: 2

Zohaib Ijaz
Zohaib Ijaz

Reputation: 22935

Just for reference, Component name should start with Capital letter

Upvotes: 43

Related Questions