React: How to create a Custom Hook

 by Robin Wieruch
 - Edit this Post

React introduced quite a while ago. With their release, Hooks gave the ability to use state and side-effects with built-in Hooks such as and .

There are only a handful built-in Hooks (e.g. , , , ) provided by React though. However, by using these Hooks as a foundation, React developers can create their own hooks called custom hooks. In this tutorial, I will walk you through creating a custom hook as a learning experience.

Before we create a custom hook, you need to know that there are two rules to creating one:

  • Custom Hooks are named with "use" as prefix. For example, a custom hook could be named useLocalStorage or useAuthentication. In our case, the custom hook will be named useBoolean.
  • Custom Hooks consist of built-in React Hooks or other custom Hooks. Therefore a custom Hook is always a new composition of one or multiple Hooks. If a custom Hook does not use any hooks internally, it's not a custom Hook and shouldn't have the prefix "use".

We will create a custom Hook called useBoolean which I almost use every time when I join a new project as a . But before we implement this hook, let's see what problem it solves for us. Let's start with a little example:

import * as React from 'react';
function App() {
const [isToggle, setToggle] = React.useState(false);
const handleToggle = () => setToggle(!isToggle);
return (
<div>
<button type="button" onClick={handleToggle}>
Toggle
</button>
{isToggle.toString()}
</div>
);
}
export default App;
false

The component renders a button which toggles a boolean. In a real world React application, there is not much you can do with a stateful boolean. Either you toggle it (like in the previous example) or you set it explicitly to true or false (like in the next example):

import * as React from 'react';
function App() {
const [isToggle, setToggle] = React.useState(false);
const handleToggle = () => setToggle(!isToggle);
const handleTrue = () => setToggle(true);
const handleFalse = () => setToggle(false);
return (
<div>
<button type="button" onClick={handleToggle}>
Toggle
</button>
<button type="button" onClick={handleTrue}>
To True
</button>
<button type="button" onClick={handleFalse}>
To False
</button>
{isToggle.toString()}
</div>
);
}
export default App;
false

Some developers may argue that we could have used instead, so there wouldn't be the repetitive declaration of event handlers. However, personally I try to avoid inline handlers as much as I can, because they inject too much logic into the JSX which instead should be defined between the component's function signature and the return statement. But that's just personal preference.

Anyway, every time you use a stateful boolean, you will encounter the same implementation details: Either you toggle the boolean or set it to one of its two possible values. To shield away this repetitive code when using stateful booleans in more than one React component, I started to create a custom hook for it:

const useBoolean = () => {
const [state, setState] = React.useState();
const handleTrue = () => setState(true);
const handleFalse = () => setState(false);
const handleToggle = () => setState(!state);
return [
state,
{
setTrue: handleTrue,
setFalse: handleFalse,
setToggle: handleToggle,
},
];
};

Essentially all implementation details, meaning the state and the event handlers, moved into this custom hook called useBoolean. In addition, the custom hook returns the state and the functions to update the state in an array.

Returning an array is a best practice when returning multiple values from a custom hook, because React's built-in Hooks -- in the case of returning multiple values -- make use of arrays and therefore array destructuring as well. Using array destructuring comes with the benefit of giving the destructured values any name (less code than renaming values in the case of object destructuring).

const useBoolean = (initialState = false) => {
const [state, setState] = React.useState(initialState);
const handleTrue = () => setState(true);
const handleFalse = () => setState(false);
const handleToggle = () => setState(!state);
return [
state,
{
setTrue: handleTrue,
setFalse: handleFalse,
setToggle: handleToggle,
},
];
};

A good addition would be adding an initial state too (as seen in the last code snippet). Back in our App component, we can make use of this new custom hook by passing an initial state to it and by using its returned values to display the state and to update it:

function App() {
const [isToggle, { setToggle }] = useBoolean(false);
return (
<div>
<button type="button" onClick={setToggle}>
Toggle
</button>
{isToggle.toString()}
</div>
);
}

Since the custom hook does not only offer the function to toggle the stateful boolean, but also to set it explicitly to true or false, we can make use of these functions too:

function App() {
const [isToggle, {
setToggle,
setTrue,
setFalse,
}] = useBoolean(false);
return (
<div>
<button type="button" onClick={setToggle}>
Toggle
</button>
<button type="button" onClick={setTrue}>
To True
</button>
<button type="button" onClick={setFalse}>
To False
</button>
{isToggle.toString()}
</div>
);
}
false

Essentially we extracted the stateful boolean and all the event handlers -- which are operating on the boolean -- into a custom hook. By using this custom hook every time we need a stateful boolean, we can spare defining the event handlers which include the implementation details about how to manipulate the boolean and instead use the functions that are returned from the hook.

In conclusion, we have learned how to create a custom hook by using one of React's built-in Hooks called useState. This custom hooks is not complex, however, it should show you how you can either reduce complexity and redundancy in your React project.


There are many custom React Hooks out there suited for various problems. Most of them can be installed via . However, whenever I find a good one myself, I try to write briefly about it. These are some of them you may want to check out:

Keep reading about 

React's useCallback Hook can be used to optimize the rendering behavior of your React function components . We will go through an example component to illustrate the problem first, and then solve…

React's useMemo Hook can be used to optimize the computation costs of your React function components . We will go through an example component to illustrate the problem first, and then solve it…

The Road to React

Learn React by building real world applications. No setup configuration. No tooling. Plain React in 200+ pages of learning material. Learn React like 50.000+ readers.

Get it on Amazon.