Easiest way to learn Custom Hooks

Oğulcan Davran
6 min readOct 31, 2020
Photo by Martin Shreder on Unsplash

TL&DR Hooks are functions, custom hooks are custom functions.

Have you ever had a hard time with hooks? Maybe you did not understand what a hook is or just mainly what a custom hook is. Despite the case, this article is intended to show an easy understanding to the new concept of React, Hooks. If you are already have a good understanding regarding hooks in general, feel free to jump into Custom Hook section.

React Hooks

React introduced hooks with React 16.8 and it has been loved and supported at great levels. Many developers left writing class components never to return, new projects are mostly written with hooks and even some projects are rewritten with hooks. Of course, this does not mean that class components are not used at all but the usage of hooks probably exceeded usage of class components.

As stated in official documentation, React’s main motivation was derived from some problems with class components.

  • It’s hard to reuse stateful logic between components
  • Complex components become hard to understand
  • Classes confuse both people and machines

Hooks solve those problems and many more. We love hooks for that but sometimes it can be confusing for developers to understand what a hook does until they learn it.

Hooks are functions.

useState

I believe it is best to start with useState, one of React’s built-in hooks. What it does is that it allows you to have a state in functional components. Mainly the job is storing the state, allowing you access to the state and update the state.

useState does all of these with the same logic of simple functions. What I mean is that, it takes a parameter and returns something. Syntax may seem strange and you may not realize that useState is just a function, but it is.

const [stateValue, setStateValue] = useState(“hello hooks”)
  • useState takes a parameter (“hello hooks”)
  • useState returns an array with state value (stateValue) and a function to update state value (setStateValue)
  • [stateValue, setStateValue] is just a way of destructuring which is nothing special to the hooks. If you are new to destructuring, I suggest you look at desctructuring first.
  • parameter is just optional initial value of the state

So if you write a functional component and print the value without destructuring, you will see that useState just returns an array with two elements. In a summary,

  • parameter is initial value
  • array[0] is state
  • array[1] is function to update state

You can have as many state value as you like.

const [name, setName] = useState()
const [surname, setSurname] = useState()

array[0] and array[1] can be assigned to any name as well. But it is a convention that you name the array[1] as the same name with array[0] with “set” word in the beginning.

function LearnHooks () { 
const [count, setCount] = useState(0) // initiate state with 0
const handleClick = () => setCount(20) // change state as 20
return (
<>
<div>{count}</div>
<button onClick={handleClick}>Change count</button>
</>
)
}

As you can see above changing state is easy. You just call the function returned from useState with the new value.

There are many built-in hooks in React. Each of them has different purpose. In the end, they are all functions built for us to make our life easier and use functional components in a better way. You can take a look at them at official documentation. Please also check the rules of hooks, even though they can be seen as simple functions at their core, they have specific rules we should

follow.

Custom Hooks

Custom Hooks are functions that can use other hooks. With custom hook, you can extract any logic into reusable function. It is the same logic that we use for regular functions. If you can extract a logic and reuse it in somewhere else, you would extract that logic and make it a seperate function for the sake of reusability, DRY and maintainability.

They are functions with a little bit of speciality. They can consume other hooks such as useState(), useEffect() or useCallback(). This allows us to consume state and life cycle methods in a reusable function. They start with “use” word as a convention and also as a way for React to determine whether a developer broke the rules of hooks.

Please take a look at this custom hook. It gives the context to the user and warn the user if you try to access a context outside of its provider. It is a simple hook but it provides the context in a simple way and we do not need to import the context every time we use and also we don’t need to check every time whether we are using inside a provider.

export default function useColor() {  
const context = React.useContext(ColorContext);
if (!context) {
throw new Error(`useColor must be used within colorProvider`);
}
return context;
}

If we are to use this hook, we simply write

import useColor from "./useColor";
const { color, setColor } = useColor(); // this value is the context value

When the value that comes from the context changes, our components that use this hook will rerender.

useInput

I would like to make a custom hook for inputs. Suppose we have a form component.

Component has three inputs

Each input has an onChange handler and state value.

Each input does almost the same thing.

For each component we have this piece of code repeatedly.

const [name, setName] = React.useState("");
const handleChangeName = (e) => {
setName(e.target.value);
};

To make this repetition a hook, simply remove the repetition and paste the repetition into a function called useInput. Also get the values from useInput() instead of useState(). Your component should look like this with lots of errors. Now we have to make these errors go away and also get the values we need from useInput hook but right now our hook does not return anything.

We know we have to return something from useInput and the way we want to use it, we have to return an array with a name and onChange handler. Instead of updating the state with our own onChange handler we want our useInput hook do that for us. In FormWithoutCustomHook component, we will receive onChangeHandlers now as a second element. We also return an array with name and handleChangeName.

Voilà! you made a custom hook. There are some small changes we can do to make it more generic. Instead of storing state as name, we can call it value and instead of handleChangeName we can call it onChange.

Also our hook receives an initial value but does not apply. We can make that work by receiving as an argument and initialize our state with the initial value.

Our hook is now ready to be used and you can use it anywhere.

I am also leaving sandboxes to play around.

useColor

useInput

useForm

Thank you for reading !

--

--