Intro
Explore custom useToggle hook use cases. Implement, type, and test it. Compare code before and after useToggle implementation for a clear understanding.
Let's understand why you may need the useToggle hook
Usually when creating components like: Dialogs, Menus, Modals, and Alerts, you need a flag that determines whether should something be displayed or not. With this flag, you need to provide 3 functions: open, close, and toggle. It will probably looks like the following code:
Loading
Imagine that you have tons of components like mentioned one and in addition in your application logic, you need to determine whether to show something or hide.
Loading
The next case may require assigning some data when you want to display UI parts - for example, you want to edit user data, so you need to store somewhere the current user object, update this object, close the form, and reset the object to initial value or just null.
Loading
This code is easy to understand but hard to maintain - the same repetitive logic, hard coded in different places. You need to write repeated tests to cover these cases for every component that needs to show/hide UI or for components that store some data during toggling.
This is the moment when lights turn on and we're kicking in with easy to use and type-safe hook. This hook will be called useToggle - it was really hard for me to find the appropriate name for this hook.
How we will use the useToggle hook?
We want to make this hook "flat" as possible to reduce the number of lines. So it will be used in the following way:
Loading
It's insane how we reduced the code from the previous example. Let's explore the full API of this hook:
Loading
Creating type definitions in TypeScript
Contracts in terms of type-safety are required to achieve protection from typos, invalid usage of functions, and invalid usage of returned data. Let's create them in separate file:
Loading
We've used generics T and we assigned the initial type to null. It means if we skip providing the generic type to hook, the default data type will be null.
Implementation process of the useToggle hook
Now it's time for implementation. With before-created type definitions, we'll be safe during implementation. Look at the following gif to understand the order and implementation process with defined contracts.
Loading
Ok, we know how it was implemented so let's explain each part of this implementation.
Loading
Now is the time for unit tests!
Unit tests for useToggle hook
We'll use the react-testing-library module that allows us to test hooks. We'll try to go through the typical use case of this hook and we'll check if the state changed correctly.
Loading
We started by assigning the initial state to our hook via configuration and then we closed, opened, toggled, and reassigned data. After each interaction, we checked the state.
Final result
Repository to play with implemented code. In addition below you have all the required code Copy and paste it and just use useToggle hook.
Look at type definitions file.
Loading
Now the implementation kicks in.
Loading
In the end the really important part - tests.
Loading
What did we learn in this lesson?
As you have probably seen, sometimes simple logic can be frustrating to work with if you need to repeat such logic in different places. This simple useToggle hook shows how you can wrap such logic inside a reusable, independent being.
What scenarios can be handled with this utility? It may be useful in creating any components like Modal, Menu, in simple words - to create something that appears and disappears.
In addition, we can assign additional data that may be useful when dealing with real business requirements or more complex components.
Everything is tested in a single place, so next time when you'll test your components you need to focus only on checking - is the useToggle hook used? If yes, you can skip testing these flags and data setup in your application/presentation-related components.
- 1. Rendering
16 minutes
Creating portals with custom usePortal hook
2 m
We will change the screens with useStepper hook
3 m
Manage components appearance with useToggle hook
4 m
Removing server warnings for useLayoutEffect with custom hook
3 m
First interaction detection with useOnInteraction hook
4 m
- 2. Forms
4 minutes
- 3. Events
26 minutes
Read the scroll metadata and direction with useScroll hook
5 m
Using clipboard with useClipboard hook
4 m
Detect outside click with the useClickOutside hook
6 m
Deep dive into useIntersectionObserver hook
4 m
Element size measurement with useElementSize hook
7 m
- 4. Guards
5 minutes
- 5. Interactions
5 minutes
Comments
Add your honest opinion about this article and help us improve the content.