bearrider
bearrider

Reputation: 322

react useRef : current value is undefined

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

Upvotes: 1

Views: 3218

Answers (2)

SomoKRoceS
SomoKRoceS

Reputation: 3053

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);
  }

Upvotes: 2

alexis_thual
alexis_thual

Reputation: 339

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.

Upvotes: 0

Related Questions