Build a React Timer Application with useRef
Tags: javascript, webdev, react, hooks
Published: 2022-05-30 22:58:31


by [Ugochukwu Prosper](https://blog.openreplay.com/authors/ugochukwu-prosper)

I need to warn you on this: if beginners learn that elements can be easily accessed by `useRef`, vanilla Javascript will be the day's order, which defiles the knowledge of state management we have learned forehand in React. As tricky as it looks, it's that powerful. `UseRef` should only be used to create a reference in our component if need be. We will dive into this in the article; you will learn some everyday use of the `useRef` React hook, and we will also build a stopwatch timer application with it. 

![The goal of this article](https://blog.openreplay.com/181535655953f279527473caf6af12c1/image01.gif)

 
## Development area 

You'll need React 18 and Node installed to follow through. If you want to install React 18, follow the steps below:

```
npm install react@18 react-dom@18
```

To take advantage of all the new features of React 18 you will need to go to your entry file, typically the `index.js`, and replace everything with this: 

```javascript
import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App';

const root = createRoot(document.getElementById("root"));
root.render(<App/>);
```

## Why useRef, and how to use it?

React state has a few limitations, and that's where React references come in handy. `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument (`initialValue`). The returned object will persist for the entire lifetime of the component.

One advantage `useRef` has over useState could be well stated as "the reference does not trigger a re-render, but in state, when state is updated it triggers a re-render.

It's key to note that we can access anything in our component and set focus to an element. As it has been said forehand, I will go ahead and illustrate how to do that, but before then, I would like to point out two essential take-home keys for the `useRef` hook:


- The value persists.
- Updating the reference does not trip on a re-render.

What exactly do we need with these keys? I will take an example of what I would like to do, to show how many times a component is rendered on the screen. A quick fix is to use the useState hook, but it will leave us with an infinite loop; let me show you.

```javascript
import React, { useState, useEffect } from 'react';
function Render() {
  
  const [render, setrender]=useState();
  useEffect(()=>{
    setrender(prevrender=>prevrender+1)
  })
  console.log(render);
  
  return (
    <>
      <div>
        This component rendered= {render} times
      </div>
    </>
  
  )
};
```
 

The code up there will lead you to an infinite loop because the state isn't the best option for things like this. If the state is not, what is? A quick fix is to use Refs.

Ref is similar to state in that it persists between renders of your component, but it doesn't cause your component to re-update when a change occurs, as earlier stated. Let's go ahead and fix the above logic using `useRef`.

```javascript 
    const render = useRef(0);
    // current {0}
```

Above is the `useRef` syntax. It returns an object by default which is the current property, which also by default sets itself to 0. Whenever the current property is updated, it persists between our various renders.

```javascript
import React, { useRef, useEffect, useState } from 'react';
function Render() {
  const [age, setAge] = useState(20);
  const render = useRef(0)
  
  useEffect(() => {
    render.current = render.current + 1
  })
  function updateAge() {
    setAge(prevage => prevage + 1)
  }
  
  return (
    <>
      <div className='center'>
        <p>This site is strictly for adults ranging from 20-...</p>
        <p>you are {age} years old</p>
        <button onClick={updateAge}>set age</button>
        <p>This state rendered {render.current} times</p>
      </div>
  
    </>
  
  )
};
  
export default Render;
```
 
![A problem in React](https://blog.openreplay.com/3ed278b0ed919fdf31c77b793824ad30/image02.gif)

 
The code up there is a simple logic for registration. Unlike using the use state hook to indicate how many times a component is rendered, using `useRef` doesn't send us into an infinite loop, and if we change `updateAge` to increment by five or whatever, it will never cause our component to re-render.

```javascript
    function updateAge() {
    setAge(prevage => prevage + 5)
    }
```

![increments by 5](https://blog.openreplay.com/8c58221d09b094d63d4eb9ece75a3b33/image03.gif)


Let's go ahead and create an input with a bit of styling and set up a reference. These are the steps we will follow to set focus;

1. We need an input field to be able to return the focus to it.
2. We need to define the reference.
3. We need a button to be able to return focus to the input element in our component.
4. We need to add the reference attribute to our element.

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

import './App.css';
  
function App() {
  const [insert, setInsert] = useState('');
  //const render = useRef()
  
  const handleOnchange = (e) => {
    setInsert(e.target.value);
  }
  
  return (
    <div className="App">
      <input
        type="text"
        placeholder='use reference'
        value={insert}
        onChange={handleOnchange}
        className="input"
      />
      <br /><br />
    
      <div> <p className='text'>{insert}</p></div>
    </div>
  );
}
  
export default App;
```

Some styles:

```
.input {
      border-radius: 10px;
      padding: 10px;
      margin: 20%;
  }

  .body {
      background-color: burlywood;
      display: flex;
      justify-content: center;
      align-items: center;
  }

  .text {
      color: white;
      margin: 0;
  }
```
  
We can now go ahead and set up a reference for it. First, by importing the `useRef` hook and defining our reference, we can name our reference `reference`.

```javascript
import React, { useState, useRef } from 'react';<-//FOCUS HERE

import './App.css';
  
function App() {
  const [insert, setInsert] = useState('');
  const reference = useRef() <-//FOCUS HERE
```    

     Then, we need to create the function that enables us to set focus on the input;

```javascript
const returnCursor = () => { 
  reference.current.focus()
}
```
 
We also need to pass the above code to our JSX. How do we do that? We need to create a button and pass the function into it, so whenever we click the button, it runs the function `return cursor`. Let's do that.

```
<div className='button'>
  <input
          type="button"
          value="Return cursor"
          onClick={returnCursor}
        />
      </div>

//a little styling
.button {
        border-radius: 10%;
        padding: 10%;
        color: black;
    }
```
    

Lastly, we need to set attributes in our input element;

```
ref={reference}
```

We have just emphasized setting focus for some time now, but then, what exactly are we setting focus to? Whenever the button is clicked, it's meant to trigger the input element, and when the element is triggered, the text cursor re-appears.


![Moving the cursor with useRef](https://blog.openreplay.com/8df784eb3d56b7921f68635c234b183b/image04.gif)


The above video illustrates what we have been able to do with `useRef`.




## Open Source Session Replay

_[OpenReplay](https://github.com/openreplay/openreplay) is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data._

![replayer.png](https://static.openreplay.com/images/banner-blog.png)

_Start enjoying your debugging experience - [start using OpenReplay for free](https://github.com/openreplay/openreplay)._





## UseRef to build a stopwatch timer

At the beginning of the tutorial, we saw a video; let's build it as we have learned the basics of `useRef`, which can enable everybody to stand out using this hook.

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

import './App.css';
  
  
function App() {
  const [insert, setInsert] = useState('');
  const [secs, setSecs] = useState(0);
  const reference = useRef(0);
  const time = useRef();
  
  const handleOnchange = (e) => {
    setInsert(e.target.value);
    reference.current++;
  }
  
  const startTime = () => {
    time.current = setInterval(() => {
      reference.current++;
      setSecs(prev => prev + 1)
    }, 1000)
  }
  
  const stopTime = () => {
    clearInterval(time.current);
    time.current = 0;
  }
  
  const resetTime = () => {
    stopTime();
    if (secs) {
      reference.current++;
      setSecs(0);
    }
  }
  return (
    <div className='App'>
      <input
        type="text"
        placeholder='use reference'
        value={insert}
        onChange={handleOnchange}
        className="input"
      />
      <br /><br />
      <div className='text'> <p className='text'>Please input your name: {insert}</p></div>
      <div >
      </div>
      <input type="button" value="start time" onClick={startTime} />
      <input type="button" value="stop time" onClick={stopTime} />
      <input type="button" value="reset time" onClick={resetTime} />
      <p>Timer{secs}</p>
      <div>
        <p>Render:[{reference.current}]</p>
      </div>
    </div>
  );
}
  
export default App;
```     

Styling:

```
.input {
    padding: 10px;
    border-radius: 20px;
    width: 70em;
}
  
.button {
    padding: 20px;
    border-radius: 10px;
    display: flex;
    justify-content: center;
    align-items: center;
}
  
.body {
    display: flex;
    justify-content: center;
    align-items: center;
}
  
.text {
    margin: 10px;
}
```

The above has a stop timer and input. It renders every second and displays the renders and the timer even when we type. Whenever the app re-renders, we do not lose the value because of the use of the `useRef` hook. 


![The final result](https://blog.openreplay.com/181535655953f279527473caf6af12c1/image05.gif)

## Conclusion 

Regularly updating the state of the React component with the use of the `UseState` hook can have unintended results. 
Overall, the take-homes are:

- We can store values in refs and have them updated, which is more efficient than `useState`, which can be costly when the values are to be updated multiple times within a second.
- The returned object will persist for the entire lifetime of the component.
- It's key to note that we can access anything in our component and set focus to an element.


[![newsletter](https://blog.openreplay.com/static/e6b18eda7a327511296a2f27692f9c70/e9957/newsletter.png)](https://newsletter.openreplay.com/)