Underrated React Hooks
Tags: react, webdev, javascript, tutorial
Published: 2021-05-09 17:34:20

# What Are Custom Hooks 👐

Considering that much of the react fanbase has switched over to using functional components, there has been an increased necessity for hooks, so today, I'll tell you about 3 custom hooks that I feel don’t get the attention they deserve. 

But first, what really is a custom hook and how do you make one? A custom hook is "a JavaScript function whose name starts with 'use' and that may call other Hooks" according to the React docs, but they typically return a value and a function that can change that value as well. For example, the `setState` hook:
```javascript
const [state, setState] = useState("initialValue")
```
returns `state` and `setState` when destructured. So, when making your own custom hook, you would do the same. It’s actually really simple. And when making your own hook, you can utilize previously created hooks and add more functionality. This is how the useLocalStorage hook below is made.

Custom hooks provide a layer of abstraction that make your code easier to read and can boost your productivity. I would advise that you try making your own in your next React project because they can be used to add any functionality. For example, the three hooks I list below allow you to use local storage, toggle between light and dark mode, and manipulate the browser clipboard.

# useLocalStorage 📍

![undraw_Memory_storage_reh0](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3dxrjmd7vgx1jk30c44f.png)

*thanks to [usehooks.com](https://usehooks.com) and [Web Dev Simplified](https://www.youtube.com/watch?v=6ThXsUwLWvc) for this one*

If you’re unfamiliar with the localStorage API, it works very similar to *cookies* in that it lets you save user data in the browser so that it’s not lost when one refreshes the page or closes the website. This could be very helpful for saving a user’s palettes on a color palette website without forcing them to sign up for example. In localStorage, data is stored in a JSON format, so you need a key and value representing the data.

The useLocalStorage hook is basically the useState hook but each state will also be saved to localStorage. A practical application of this is saving a user's current song and saved songs which I did when making a personal music player. In the code below which I pulled from my project, you can see that I just built upon the useState hook:

```javascript
import { useState, useLayoutEffect, useEffect } from "react";

export default function useLocalStorage(key, value) {
    const [state, setState] = useState(value)

    useLayoutEffect(() => {
        const data = localStorage.getItem(key)
        setState(JSON.parse(data))
    }, [])

    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(state))
        }, [state])

    return [state, setState]
}
```

Let me explain the parts of this snippet:
* **`useLocalStorage(key, value)`** - Similarly to useState, this hook will take in the initial value but it will also require a key 

* **`const [state, setState] = useState(value)`** - initializing the state with the value parameter

* **`useLayoutEffect(...)`** - there are two useEffects used, but this first one is used to grab the items from localStorage, and since there are no dependencies, it only runs once on the mounting of the component. I utilized useLayoutEffect because it runs before the component is mounted rather than after. This prevents the problem of the content rendering the default data and then changing to the localStorage data one second later. 

* **`useEffect(...)`** - the second useEffect is used to set the new state to localStorage, and has the state as a dependency so that it saves to localStorage upon each change of the state. Read [this](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to learn more about localStorage methods such as setItem and getItem which I used above

* **`return [state, setState]`** - this is the part that establishes the function as a hook. You can replace all your calls to setState with this function now because it can also be destructured in the same way. You just need to add the key as a first parameter

# useDarkMode 🌕🌗🌑

![dark-mode-5771054_1280](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p7q9ej9xbrdvvvgxwz6g.png) 

In the modern day, dark mode is essential for any portfolio website, so why not create a reusable hook that simplifies the process? 

For this hook, I am not going to show the code that makes the hook because it's a little more advanced, but you can check it out [here](https://github.com/donavon/use-dark-mode/blob/develop/src/index.js). Nonetheless, I will still show you how to use it once it has been defined. This hook actually returns an object with the value and the functions required to toggle, enable, and disable dark mode, but it's still the same concept just written in a different way. You will need to write a little CSS to configure how your light mode and dark mode will look, but the toggling can be handled by the hook.

```javascript
import useDarkMode from 'use-dark-mode';

const DarkModeToggle = () => {
  const darkMode = useDarkMode(false);

  return (
    <div>
      <button type="button" onClick={darkMode.disable}>
        ☀
      </button>
      <input type="checkbox" checked={darkMode.value} onChange={darkMode.toggle} />
      <button type="button" onClick={darkMode.enable}>
        ☾
      </button>
    </div>
  );
};
```

Code explanation:
* **`const darkMode = useDarkMode(false)`** - the "false" passed to the hook specifies that it will be in light mode by default

* **`\<button type="button" onClick={darkMode.disable}>`** - since the return value of the hook is an object, you can call darkMode.disable to change the state

* **`\<input type="checkbox" checked={darkMode.value} onChange={darkMode.toggle} />`** - the value returned by the hook is either true or false, so you can set checkboxes or toggles to the right mode with the "checked" attribute


# useClippy 📋

![undraw_photocopy_gj0t](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8le6b9qh6xhw76nphx1e.png)

useClippy is a hook that allows you to view your copy/paste clipboard and copy items to the clipboard. This can be used to make a button which copies a URL when clicked for example.

Again, with this hook, I will only show the code used to apply it, but you can view the actual hook [here](https://github.com/CharlesStover/use-clippy/blob/master/src/use-clippy.ts) (written in Typescript though)

```javascript
import useClippy from 'use-clippy';
 
export default function MyComponent() {
  const [clipboard, setClipboard] = useClippy();
 
  return (
    <div>
      <button
        onClick={() => {
          alert(`Your clipboard contains: ${clipboard}`);
        }}
      >
        Read my clipboard
      </button>
 
      <button
        onClick={() => {
          setClipboard(`Random number: ${Math.random()}`);
        }}
      >
        Copy something new
      </button>
    </div>
  );
}
```

Code explanation:
* **`const [clipboard, setClipboard] = useClippy();`** - useClippy is destructured the same way as useState but returns the last thing on the clipboard and a function to save to the clipboard

* **`<button>...</button>`** - the buttons grab the last thing from the clipboard and set new items to the clipboard on click (pretty self-explanatory)

# Conclusion 👊

Feel free to leave any custom hooks you've found or made that didn't make it on this list.