Custom Hooks - useTime()
Tags: webdev, react, typescript, javascript
Published: 2023-02-26 21:53:26

Hi everyone,

Today I come to you with an example of one of the most difficult processes in React: Creating your own hook! 

I decided to start with an easy example first. Therefore, we will create a hook called **useTime()** with you. Let's get started!

I'm starting by assuming you have created your React project because I don't want to take your time for it.

First, we can create a directory called hooks to keep our code organized. Then we have to create the required files here: **useTime.ts** and **index.ts**.

Since I use React with Typescript language, the extension of my files appears as **_.ts_** and the content is written in the typescript language.

Also, one of the important things to mention is the naming convention for custom hooks. Your hook function must have a name that will follow the use....() pattern. Otherwise, you will not be able to use the built-in React hooks in an external file and you will encounter an error like the one below.

`Line 4:41: React Hook "useState" is called in function "donotuseTime" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use".`

After this part, your file structure and code should be as follows.

![File structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwvid9di462yleagbnsw.png)
```typescript
/* Initial file content */
const useTime = () => {};

export default useTime
```

## How to implement useTime() hook?

First of all, I want to talk about the purpose of this custom hook. Let's say you want to access the time object instantly anywhere in your application and show the time on the screen. In this case, you can get a perfect abstraction using the useTime hook.

We will use 2 built in react hooks to implement this hook: 

1. **useState**
2. **useEffect**

You can see the whole implementation and explanations of each part below.

## Implementation

```typescript
import { useEffect, useState } from "react";

// Part 1
const useTime = (refreshPeriod: number = 1000) => {
  const [currentTime, setCurrentTime] = useState<Date>();

  // Part 2
  useEffect(() => {
    // Part 3
    const interval = setInterval(
      () => setCurrentTime(new Date()),
      refreshPeriod
    );
    // Part 4
    return () => clearInterval(interval);
  }, [refreshPeriod]);

  // Part 5
  return currentTime;
};

// Part 6
export default useTime;
```

## Explanations

**Part 1**
We name our function using the use....() pattern and take the necessary arguments. The argument we receive here specifies how many milliseconds our function will run, namely the refresh period.

**Part 2**
Here, we use the useEffect hook to make a function run when certain parameters change. The parameter we get here is the **refreshPeriod** parameter. If there is a change in this parameter, the function we specified will work again.

**Part 3**
With the **setInterval** function, we define a function that is called continuously at certain time intervals. Here we define the interval as the refresh period value that we take as a parameter.

**Part 4**
The useEffect function allows us to return a function that is used to run when component is unmounted. In this way, we prevent memory leaks by clearing our interval when the component is unmounted.

**Part 5**
We specify how to return a value when the useTime hook is used. In this way, the returned value becomes the state that we defined it and update it at certain intervals.

**Part 6**
Exporting that hook as a default export.


## Usage

We explained everything clearly. Now the rest is using this hook in our source code. Below is the **App.tsx** file. When we use it as shown in this file, we should see the result shown below.

```typescript
import React from "react";
import { useTime } from "./hooks";

function App() {
  const time = useTime();

  return <div>{time?.toString()}</div>;
}

export default App;
```

![useTime Hook Usage Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xwrfxd1spq4msrxxnbqc.png)