1

I'm following a beginner's tutorial for the useState and useRef hooks, trying to implement a simple timer in react.

I'm using the interval variable to store the value from setInterval()

On click of start button, I am able to console.log the value of the interval correctly. However on click of stop button, interval.current is console logged as undefined. The stopTimer() hence does not function as expected.

Why does interval.current print undefined when it is clearly set in startTimer (and logged there)? What am I missing here?

import React, { useState, useRef } from 'react';

const pad = (time) => {
  return time.toString().padStart(2, "0");
};


function App() {
  const [title, setTitle] = useState("Pomodoro!");
  const [timeLeft, setTimeLeft] = useState(5);
  const interval = useRef(null);

  const startTimer = () => {
    interval.current = setInterval(() => {
      setTimeLeft((timeLeft) => {
        if (timeLeft >= 1) {
          return timeLeft - 1;
        }
        return 0;
      });
    }, 1000);
    console.log(interval.current, " :in start");
  }

  const stopTimer = (interval) => {
    console.log("in stop: ", interval.current);
    clearInterval(interval.current);
  }

  const resetTimer = () => { }

  const minutes = pad(Math.floor(timeLeft / 60));
  const seconds = pad((timeLeft - minutes * 60));


  return (

    <div>
      <div>{title}</div>
      <div>
        <span>{minutes}</span>
        <span>:</span>
        <span>{seconds}</span>
      </div>
      <div>
        <button onClick={startTimer}>Start</button>
        <button onClick={stopTimer}>Stop</button>
        <button onClick={resetTimer}>Reset</button>
      </div>
    </div>
  );
}

export default App;

output in console

6 " :in start" in stop: undefined

Thanks

2 Answers 2

2

I believe it is because you pass a lower scope variable called interval to stopTimer, but when you call stopTimer you do not pass the argument, so it is undefined when you're accessing it.

You probably referring to interval you've defined as ref so you need to just access it without passing interval to stopTimer, try this:

  const stopTimer = () => {
    console.log("in stop: ", interval.current);
    clearInterval(interval.current);
  }
Sign up to request clarification or add additional context in comments.

Comments

0

Considering what your code is doing, I believe interval should be a state variable and not a ref. That is to say, you should use

const [interval, setInterval] = useState(null);

instead of const interval = useRef(null);

Refs are used to be linked to DOM elements (for instance a form element you wish to refer to when a button is clicked). It's only when a ref variable is correctly referencing a DOM element that their current attribute is defined.

1 Comment

Though ref is often used to anchor DOM elements, it's not restricted to that.

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.