React Custom Hooks #3: Simplify Your Code with useToggle and useBoolean

Learn how to simplify your React code with the useToggle and useBoolean custom hooks. Discover how these hooks can help improve user experience, while reducing coding complexity.

#react
#javascript
#hooks
React Custom Hooks #3: Simplify Your Code with useToggle and useBoolean
Picture by Marco

One of the most loved aspects of React is the way it allows one to conditionally render components and single elements. A feature that, among many others, brought the library to be the most loved in the JavaScript ecosystem.

Since we base all our conditionals on truthiness and falsehood, we use to repeat common scenarios where is necessary to switch a boolean to its opposite or we consistently need to switch a flag to a specific value.

Check your code and tell me: are you repeating a lot of code across different components. I guess we both know the answer, right?

This is the reason why, with few lines of code, is possible to abstract a couple of custom hooks which will make our components way more readable. This is why useToggle and useBoolean have become my favourite React custom hooks!

The perfect use case: a Modal component

Modals are common components used in any modern web app, they are good for announcements and aside communications to the user.

Under the technical behaviour, they usually need to be opened or closed and we may want to toggle their appearance on the screen when clicking a button.

Look at this example and keep in mind how we handle the Modal creating various handlers, we’ll need it later for comparison purposes.

jsx
function App() {
const [isOpen, setOpen] = useState(false);

const openModal = () => setOpen(true);

const closeModal = () => setOpen(false);

return (
<Container>
<Button onClick={openModal}>Open the modal!</Button>
<Modal open={isOpen} onClose={closeModal}>
<Button onClick={closeModal}>Close the modal!</Button>
</Modal>
</Container>
);
}

Do you see the openModal and closeModal handlers? Now imagine you have to use a Modal on different pages and control its behaviour with different UI interactions than simple buttons.

Do you want to rewrite all those handlers every time? Nope, thanks!

useToggle

The first custom hook we need to create is useToggle.

It allows you to immediately toggle a boolean value with no need to create a function for it. It is useful in most cases to handle checkbox components, hidden elements and much more, I consider it the basic piece for handling conditional renders.

js
import { useReducer } from 'react';

function toggler(currentValue, newValue) {
return typeof newValue === 'boolean' ? newValue : !currentValue;

function useToggle(initialValue = false) {
return useReducer(toggler, initialValue);
}

export default useToggle;

It uses the useReducer hook to define the implementation of the dispatch function, to switch to its opposite value when it gets called.
The benefit of this approach is that the dispatch function is always memorized, so you can pass its reference to any event prop without triggering a rerender of this component that receives it.

In this example, you can see how it makes clearer the implementation of a hidden element:

jsx
function App() {
/*
* Before
*
* const [isShown, setShown] = useState(false)
* const toggle = () => setShown(!isShown);
*/

// After
const [isShown, toggle] = useToggle();

return (
<Container>
<Button onClick={toggle}>{isShown ? 'Hide' : 'Show'}</Button>
</Container>
);
}

May I be wrong, but it looks incredibly clean to me ✨

useBoolean

Now that the useToggle hook is a reality and we know how to use it, the useBoolean hook will show us why composability and reusability are pillars of the React paradigm.

A couple of minutes ago we have seen the usage of a Modal component and all the necessary handlers open/close it. It shows us that we need all the possible ways of setting a boolean value. And this is what the useBoolean hook is made for. Eyes on the screen, and let’s read the implementation:

js
import { useMemo } from 'react';
import useToggle from '@mountain-ui/react-hooks';

function useBoolean(initialValue = false) {
const [value, toggle] = useToggle(initialValue);

const handlers = useMemo(
() => ({
toggle,
on: () => toggle(true),
off: () => toggle(false)
}),
[toggle]
);

return [value, handlers];
}

export default useBoolean;

Similarly to useToggle, it returns an array that holds as the first element the value, and as the second argument it returns an object with all the possible handlers that allow setting the boolean:

  • on: switch the boolean to true.
  • off: switch the boolean to false.
  • toggle: the same handler returned from the useToggle call.

As you can see we reuse the useToggle hook to abstract some internal logic, and we wrapped our handlers with the useMemo hook to always provide the same reference of our handlers.

At this point, we get a new fresh custom hook to handle our Modal appearance. It’s time to refactor my previous implementation to improve its readability and abstract all those verbose handlers!

jsx
function App() {
/*
* Before
*
* const [isOpen, setOpen] = useState(false);
* const openModal = () => setOpen(true);
* const closeModal = () => setOpen(false);
*/

// After
const [isOpen, { on: openModal, off: closeModal }] = useBoolean();

return (
<Container>
<Button onClick={openModal}>Open the modal!</Button>
<Modal open={isOpen} onClose={closeModal}>
<Button onClick={closeModal}>Close the modal!</Button>
</Modal>
</Container>
);
}

That’s it, clear and descriptive about what we are managing inside the application! The scenarios where you may want to use it are many more, this is only one of the most common when conditionally rendering something on the screen.

Conclusion

With these two custom hooks in your arsenal, your React skills and confidence will grow quicker than ever!

You can also find more about the resources I’m using on the following pages:

Thanks for taking the time to read it, see you with the next post! 🚀

Last updated: