DEV Community

Cover image for An introduction to custom React hooks
Tom Mitchelmore
Tom Mitchelmore

Posted on • Edited on

An introduction to custom React hooks

As someone who's written React for several years now, it took me far too long to discover the joy of custom hooks - in fact it took me over 3 years! In this post, I'm going to show you how to take advantage of one of React's most powerful features.

What even is a hook?

A hook is quite simply a function which lets you hook into React's rendering lifecycle. Let's briefly look at the most common hook useState:

const [state, setState] = useState(0)
Enter fullscreen mode Exit fullscreen mode

As you can see, useState hooks into React and provides an interface for managing state - it's entirely abstracted away the complexity that would otherwise be associated with it.

When we think of hooks as reusable abstractions, it makes them easier to reason about. As a component is reusable markup, a hook is just reusable logic!

I like to refer to React's built-in hooks as atomic - in that we typically use and combine them to build our own custom ones.

Our first custom hook

Let's build a basic custom hook to manage the state of a toggleable component (modal, dropdown, etc):

useToggle.ts

import { useState } from "react";

function useToggle(initial = false) {
  const [state, setState] = useState(initial);

  return [
    state,
    {
      open: () => setState(true),
      close: () => setState(false),
      toggle: () => setState((state) => !state)
    }
  ] as const;
}

export default useToggle;
Enter fullscreen mode Exit fullscreen mode

Quick tip: using as const on our return value tells TypeScript to infer the type as a readonly tuple instead of a union type array! 😁

In this example, all we've done is wrap the use state hook with some logic that would otherwise pollute a component - look how easy it is to implement:

App.tsx

function App() {
  const [state, { open, close, toggle }] = useToggle();

  return (
    <div className="App">
      <button onClick={open}>Open</button>
      <button onClick={close}>Close</button>
      <button onClick={toggle}>Toggle</button>
      {state && <div>Hello!</div>}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

...and that's it! I hope that after seeing this you can start to see how you might implement other hooks - try useQueue and useStack.

In a future post I'll detail how to implement some more complicated behaviour, and some common design patterns for handling refs, external data and more.

Top comments (1)

Collapse
 
scriptkavi profile image
ScriptKavi

Why create one when you can get all awesome hooks in a single library?

Try scriptkavi/hooks. Copy paste style and easy to integrate with its own CLI