Introduction to Custom Hooks - useToggle & useAxiosAsync
Published: 2021-03-23 21:12:22

---
canonical_url: https://ogzhanolguncu.com/blog/intro-to-custom-hooks
title: 'Introduction to Custom Hooks - useToggle & useAxiosAsync'
---

Custom hooks become a staple in our lives after we got introduced to hooks such as **useEffect**, **useState**, **useReducer**. Regardless of their purposes, custom hooks should start with  `use` such as `useAxiosAsync` or `useToggle`. Therefore we can easily perceive that this is a custom hook. We could name them differently, but that would make them harder to detect at the first sight this is why the community following that convention.

Like in any other area of programming we always want to make things re-usable by detaching them from the main code. We, either turn them into functions or classes, but we are dealing with states so we want to be able to utilize react related stuff as well.

Thus we can achieve a couple of things:

- DRY(Don't repeat yourself)
- Reduced coupling
- Modular code
- Testable code

Let's take a look at this easy example:

### useToggle

```javascript
import { Alert, Button, Flex, Text } from '@chakra-ui/react';

function App() {
  const [on, toggle] = React.useState(false);
  return (
    <div>
      <span>{on ? 'ON' : 'OFF'}</span>
      <button onClick={() => toggle((prevState) => !prevState)}>TOGGLE</button>
      <button onClick={() => toggle(true)}>SET TOGGLE ON</button>
      <button onClick={() => toggle(false)}>SET TOGGLE OFF</button>
    </div>
  );
}
export default App;
```

This example is very different from where we toggle for `Loading` state while making a request for our APIs. Just on and off it's that simple. If we want this to be a custom hook, all we have to do is take `useState` out of this component and check for conditions while toggling state.

```javascript
import { useState } from 'react';

const useToggle = (initialState = false) => {
  const [toggle, setToggle] = useState(initialState);

  const toggleState = (state?: false | true) => {
    setToggle(typeof state === 'boolean' ? state : !toggle);
  };
  return [toggle, toggleState] as const;
};

export default useToggle;
```

Now, using our custom hook in the same component as we did before.

```javascript
import { Alert, Button, Flex, Text } from '@chakra-ui/react';
import useToggle from './useToggle';

function ToggleWithHook() {
  const [on, toggle] = useToggle(false);
  return (
    <div>
      <span>{on ? 'ON' : 'OFF'}</span>
      <button onClick={() => toggle()}>TOGGLE</button>
      <button onClick={() => toggle(true)}>SET TOGGLE ON</button>
      <button onClick={() => toggle(false)}>SET TOGGLE OFF</button>
    </div>
  );
}

export default ToggleWithHook;
```

Let's take a look at a more complex example, where we also use `Generics` in Typescript.

### useAxiosAsync

```javascript
type JokeType = {
  created_at: string;
  icon_url: string;
  id: string;
  url: string;
  value: string;
};

function AsyncWithoutHook() {
  const [joke, setJoke] = useState<JokeType | null>(null);
  const [error, setError] = useState<AxiosError<Error> | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const fetchAJoke = async () => {
    setIsLoading(true);
    try {
      const { data } = await axios.get<JokeType>('https://api.chucknorris.io/jokes/random');
      setJoke(data);
      setIsLoading(false);
    } catch (error) {
      setError(error);
      setIsLoading(false);
    }
  };

  useEffect(() => {
    fetchAJoke();
  }, []);

  if (error) return <Flex>{error}</Flex>;
  if (isLoading) return <Flex>Loading...</Flex>;

  return (
    <Flex flexDirection="column" boxShadow="outline" rounded="md" width="50%" padding="1rem">
      {joke?.value}
      <Button onClick={fetchAJoke}>Fetch Again!!!</Button>
    </Flex>
  );
}

export default AsyncWithoutHook;
```

Now, using custom hooks, again.

```javascript
import { Button, Flex } from '@chakra-ui/react';
import React from 'react';

import useAxiosAsync from './useAxiosAsync';

type JokeType = {
  created_at: string;
  icon_url: string;
  id: string;
  url: string;
  value: string;
};

function AsyncWithHook() {
  const [{ data, isLoading, error }, fetchAJoke] = useAxiosAsync<JokeType>(
    'https://api.chucknorris.io/jokes/random',
  );

  if (error) return <Flex>{error}</Flex>;
  if (isLoading) return <Flex>Loading...</Flex>;

  return (
    <Flex flexDirection="column" boxShadow="outline" rounded="md" width="50%" padding="1rem">
      {data?.value}
      <Button onClick={fetchAJoke}>Fetch Again!!!</Button>
    </Flex>
  );
}

export default AsyncWithHook;
```
We've shortened our component quite a bit by moving state related things to our `useAxiosAsync`. So, we no longer need to deal with business logic in our component and of course, we can use this `useAxiosAsync` whenever we want.

## Roundup

In the essence, custom hooks are just `useState` and `useEffect` **(of course other hooks as well)** hooks moved to another file to reduce the amount of code in components.
So, if something bloating your component or you keep using same logic in other components, it's time to convert it into custom hook.

**Thanks for reading 🥳🥳🥳.**