DEV Community

Cover image for How to: React custom hook
Tom
Tom

Posted on • Updated on

How to: React custom hook

Plenty of blog posts that focus on the fundamentals of implementing Hooks have already been written, so rather than add another one to the pile, I thought it might be a good idea to expand into some less-explored space.

The first part of this post touches on the motivation for using Hooks in the first place. Following code-alongs is a great way to learn, but sometimes tutorials skimp when it comes to providing reasoning for doing things in a certain way, which, as a skeptical person, always makes me feel a little uneasy.

So, I wrote the same component twice, once as a class, then as a function, and compared and contrasted them.

The second part is a tutorial on writing custom hooks to extract repetitious logic.

I hope you find the content useful!

Let's begin!

Class component
Alt Text

Why use hooks?

In a sentence, hooks save time and are clean.

Here's how:

They reduce boilerplate

Compare the two components above which render identical DOM elements. Note how Function components require no constructor or render functions, and no this* keyword (written 7 times in the Class component!) is required to bind toggleMode() or when calling methods to change state.

Unsure about this? Tyler McGinnis breaks it down very well here.

They reduce decision-making overhead

Using only Function components reduces decision-making overhead simply because we never have to make a choice between Class and Function.

  • Should this be a Function or Class component?
  • Would refactoring this to a Class be a pain if I need to add state?
  • Am I positive that it will always/never need state?

Prior to the release of the useState Hook, we had no choice but to use Classes for statefulness, but all of the questions above become moot once you've embraced the Function-Hook paradigm.

They reduce refactoring

One of the more common implementation details that changes through the development cycle of React applications is the addition of state to a component. With Function-Hooks, you can immediately add state and skip the preliminary step of rewriting to Class.

Reusing useState in a custom Hook

The second part of this post is a short tutorial on writing a custom hook. If you would like to follow along (suggested!), code is available here, including starter code and solutions.

Another BIG advantage of Hooks is that they are re-usable, which helps us keep solutions nice and DRY, another way to save time and keep code clean.

Example

Adding items to a shopping cart is a common usecase for state in ecommerce applications.

Take a moment to review code for the FruitStand component below, and we'll resume underneath when you're done.
Fruit Stand UI

Fruit Stand Component

If the repeated increment logic smells a little off ๐Ÿ’ฉ, that's a good sign! This is the redundant code that we will extract into a single custom Hook, useIncrement.

custom hook, useIncrement

A couple of details to note:

  • Because there is no JSX, there is no need to import React.
  • State and the function that changes it, increment(), are returned by the hook in an array and accessed by destructuring in the familiar [foo, setFoo] = useHook(<initial value>) pattern

Reformatting FruitStand

Reformatting the component is very straightforward.

  • Import useIncrement
  • Remove the useState import
  • Implement useIncrement for both fruit types at the top of the component.
  • delete the redundant incrementApples and incrementOranges functions
  • re-assign add button onClick to the state-setting functions of useIncrement for apples and oranges.

Here's the finished product
reformatted fruit stand component

Challenge!

Implement a decrement function for apples and oranges, using a Hook called useDecrement. No negative values allowed ๐Ÿ˜€

Conclusion

This single component example is very simple, so the benefits of useIncrement might not be obvious, but I'm sure you can imagine a situation in the real world where extracting repeated logic would be beneficial.

I hope I've made a strong case that Function components with useState have the potential to decrease development time in multiple ways, and provide a much cleaner and readable way to write stateful components.

Discussion (0)