Create Your Own React Hooks | Part 1

You can create your own hooks to encapsulate component logic into functions that can be reused.

Tariq Abdullah
4 min readFeb 23, 2021

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class

If you are reading this article then most likely you have already used React Hooks. You probably used the good old reliable useState hook for basic setting and getting of local state in a functional component. And you may have also used the powerful useEffect hook to generate side effects after every render!

Your goal now surely is to further leverage the power of hooks by creating your very own custom hooks. If so, then you have come to the right place!

But first, here is a quick refresher on these two popular built-in hooks:

useState:

This hook is used to build basic local state. Note that the declaration syntax for useState is concise. We declare both the state variable and the setter function in one statement in the form of a deconstructor:

[count, setCount] = useState(0);

After that we are all set to use both the variable and the setter function in our functional component as follows:

  return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);

useEffect:

If you’re familiar with React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.

After importing useEffect, you simply add it to your functional component in the form of a function call:

useEffect(() => {    document.title = `You clicked ${count} times`;  });

In the above example useEffect will be called on every render. You can optimize this functionality by using a memoization-like feature. This can be done by adding a second parameter to the hook as follows:

useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]);

This will result in useEffect being called only when the variable count changes! Another form of useEffect ensures that it is called only once. This is possible by using an empty array for the second parameter as follows:

useEffect(() => {
document.title = `You clicked ${count} times`;
}, []);

If you would like to look further into these two commonly used hooks useState and useEffect before you continue reading this article please read the documentation on React Hooks here.

Creating a custom hook is easy. Basically, you will be using one or more built-in hooks to build a new function that encapsulates some reusable custom logic or functionality.

In addition to the aforementioned built-in hooks useState and useEffect, here are examples of some additional built-in hooks that you may find instrumental in building your own custom hooks:

useReducer:

This hook is a favorite among Redux fans. It is considered a great alternative to the basic useState hook when there is a need to manage more complex state logic.

One big advantage that his hook touts over a full-fledged Redux implementation is the elimination of so much boiler-plate code!

Look how simple it is to set it up:

const [state, dispatch] = useReducer(reducer, initialState);

Now you can create the reducer function just as you would with a standard Redux flow:

function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}

Finally, just as you would with classical Redux, use the dispatch function to trigger an action along with an optional payload as your gateway to the store:

return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);

useRef:

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

This hook is powerful yet easy to use. You can quickly instantiate a useRef object like so:

const inputEl = useRef(null);

And use it in any of your custom hooks that offer functionality that relies on access to the DOM such as an input element that needs to get focus:

inputEl.current.focus();

All you have to do is set the ref attribute of the DOM element to the useRef object as follows:

<input ref={inputEl} type="text" />

Note that useRef is much more than just a ref attribute. It’s real power is realized when it is used to persist any mutable value just like instance fields in classes. useRef will return the same ref object on every render!

That’s it for now!!

Stay tuned for Part 2. We will take a handful of these amazing built-in hooks and use them to build our own customized React hook!

--

--