Adam Hunter

Made with in NYC

Custom React Hooks

Create your own React hooks

12.27.22

Very often, I see new developers asking whether or not they should be using class based or functional React components. The answer is always functional components and the reason is simple: hooks.

Introduced in React version 16.8, which was released in February 2019, hooks offer a way to manage state and lifecycle methods in React components without having to write classes. Hooks quickly became best practice and industry standard for React. Hooks offer increased readability of React code and let you split components into smaller functions. The official recommendation for writing class based components is just to use them on legacy code bases that are already using them. The official React docs even admit that “classes confuse both people and machines”.

React architecture emphasizes modular components and a React component is essentially a JavaScript function that will return HTML. Some React components just do that, return some HTML. Those components are known as pure functions or stateless components. A stateful component declares and manages local state in it. Keeping in step with the modular React architecture, isolating the logic to manage the state and side effects to be reusable is exactly what a hook is.

React provides about a dozen standard built-in hooks out of the box. I don’t want to go too deep listing and explaining them all here because that could be its own blog post. The two most common built-in hooks are useState and useEffect, in fact you would probably be hard pressed to find a React code base that does not have useState or useEffect anywhere in the project. Conveniently, these two are all you really need to start building your own custom hooks.

If you are totally new to React hooks, here’s a quick explanation of useState and useEffect. The useState hook allows you to set an initial state variable and then use it in the component or render that variable in the returned HTML. The useState hook uses the JavaScript array destructuring syntax which is easier to read and understand compared to the way you have to bind state in a class based component.

The useEffect hook is used for manually changing the DOM from React components. Those operations are called side effects. The useEffect hook replaces the component class based lifecycle effects componentDidMout, componentDidUpdate, and componentWillUnmount. In plain English, you use useEffect when you need to set something after React updates the DOM, or when a page or component loads or refreshes.

Why build a custom hook in the first place? There are a ton of great use cases and reasons to build your own custom hooks. Data fetching can often be redundant and whether you use the JavaScript fetch API or Axios, creating a useFetch custom hook can be helpful. When building an e-commerce store, the shopping cart is an excellent example for building custom hooks. A useCart hook can persist store items to local storage, remove the items, and then use the items for the checkout process. A custom hook for dark mode is a cool use case. Adding event listeners as custom hooks is also really cool and the specific use case that I will end with as an example.

You may have noticed, the standard naming convention for React hooks is to name them with ‘use’ in the beginning of the title to easily identify them. Other than that they are just JavaScript functions that will use at least one built-in React hook. I want to show a really cool and simple custom hook I use in a lot of projects. As I mentioned in the last paragraph, this custom hook uses an event listener to detect when scrolling occurs on a page. I often use it to change the color or size of an element when you scroll on a page. It is a cool trick to have a navigation header transition as you scroll.

import { useState, useEffect } from 'react'

export default function useScrollPosition() {
const [scrollPosition, setScrollPosition] = useState(0)

useEffect(() => {
    const updatePosition = () => {
        setScrollPosition(window.pageYOffset)
    }

    window.addEventListener('scroll', updatePosition)

    updatePosition()

    return () => window.removeEventListener('scroll', updatePosition)
}, [])

return scrollPosition
}

First we set a default state value to the scroll position using the built-in useState hook. Then inside of the built-in useEffect hook, so when the the page finishes loading this hook will execute, we have a function that will set that state variable to the window.pageYOffset, which returns the number of pixels the document is currently scrolled along the vertical axis (up or down) on the page. Then the actual event listener is added with the new function. This hook tracks how many pixels have been scrolled, so I use it in a conditional statement; i.e. if useScrollPosition > 0 change color.
Hooks really are super cool and can help you make your code both flexible and tailored exactly to your needs.
Adamadam hi

Adam