2

I'm trying to make an countdown website for a project. I want that the countdown is triggered by a button. I'm using React but i keep getting this error

React Hook "useEffect" is called in function "countdown" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter

I'm pretty new to react, can somebody give me some advice to fix the problem ?

the code:

import './App.css';
import React, { useEffect, useState } from 'react';

function App() {
  const time = 20;
  const [count, setCount] = useState(time);

  const startCount = () => {
    useEffect(() => {
      if (count > 0) {
        setTimeout(() => setCount(count - 1), 1000);
      } else {
        setCount('Times up');
      }
    });
  };

  return (
    <div className="App">
      <div>{count}</div>
      <button onClick={startCount}> start </button>
      <button> pauze </button>
    </div>
  );
}

export default App;
3
  • 4
    useEffect enables you to run something whenever the the component is rendered or when a state changes. Having that inside of a function that is called on click makes it useless. useEffect should call other functions, but should never be called from within a function. Commented Apr 6, 2021 at 19:34
  • Does this answer your question? Implementing a countdown timer in React with Hooks Commented Apr 6, 2021 at 21:07
  • With a button: stackoverflow.com/q/62294102/1218980 Commented Apr 6, 2021 at 21:08

5 Answers 5

3

You can use setInterval instead of using setTimout

Fix your code to this:

import './App.css';
import React, { useEffect, useState } from 'react';

function App() {
  const time = 20;
  const [count, setCount] = useState(time);
  const [isStart, setIsStart] = useState(false);


    useEffect(() => {
      if (isStart) {
        const timer = setInterval(() => {
          if (count > 0) {
            setCount(count - 1)
          } else {
            setCount('Times up');
            clearInterval(timer);
          }
        }, 1000);
      }
    }, [isStart]);


  return (
    <div className="App">
      <div>{count}</div>
      <button onClick={() => setIsStart(true)}> start </button>
      <button> pauze </button>
    </div>
  );
}

export default App;

You're trying to add useEffect inside a plain javascript function, that is why it throws an error that the useEffect you called is in a function that is not a React function component.

Sign up to request clarification or add additional context in comments.

Comments

1

useEffect should not be put inside a function. You do not need that start count function. onClick can update a state, and let useEffect listen to the change of that state.

Comments

0

Rules for hooks:

✅ Don’t call Hooks from regular JavaScript functions.

✅ Call Hooks from React function components.

✅ Call Hooks from custom Hooks.

You are calling hook (useEffect) from a plane javascript function which is against the rules of hooks.

Comments

0

You should not call hooks in plain js functions, you can solve your issue like this

import './App.css';
import React, { useEffect, useState } from 'react';

function App() {
  const time = 20;
  const [count, setCount] = useState(time);
  const [start, setStart] = useState(false)

  useEffect(() => {
    if (start) {
      if (count > 0) {
        setTimeout(() => setCount(count - 1), 1000);
      } else {
        setCount('Times up');
      }
    }

  }, [count, start])

  const startCount = () => {
    setStart(true)
  }

  return (
    <div className="App">
      <div>{count}</div>
      <button onClick={startCount}> start </button>
      <button> pauze </button>
    </div>
  );
}

export default App;

3 Comments

This will cause an infinite loop, because the useEffect is listening the count state and executes again the setCount in a 1 second timeout.
@Techuila no it would not, please check the code sandbox here, also check the console to see the update log. codesandbox.io/s/ecstatic-almeida-90qky?file=/src/App.js
@Techuila no worries. Please revert the downvote if it was from you. Thanks
0

useEffect hook don't use in any child function of body component function

import React, { useEffect, useState, useCallback } from 'react';
function App() {
  const [count, setCount] = useState();
  useEffect(() => {
    if (count > 0) {
      setTimeout(() => setCount(count - 1), 1000);
    } else {
      setCount('Times up');
    }
  }, [count]);
  return (
    <>
      <div>{count}</div>
      <button onClick={() => setCount(20)}> start </button>
      <button> pauze </button>
    </>)
}
export default App;

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.