Making a Custom Visibility React Hook

React Hooks are fantastic. They have have greatly streamlined my codebase and made it easier to develop and maintain complex components. This post is not going to be a primer on hooks. If you are not familiar with hooks, go check out the React docs or this tutorial by Kent C. Dodds on Egghead.

A lot of the apps I build make use of components like drawers and dialogs. These components require that I track their visibility state (i.e. open or closed). Nothing too complex here. Most of the time you can just handle this through the useState hook. However, I found that in some instances I wanted to explicitly set the visibility state to true or false and in some instances I just wanted to toggle the current state. Again, easy enough.

I got tired of writing the same logic across multiple components though and decided to refactor things into a custom useVisibility hook. The hook returns the current state value as well as a handler for updating the visibility state. The update handler takes an optional value argument. If the value argument is provided, it sets the state to the provided value. If no value argument is provided, it sets the state to the opposite of the current value. Here is the hook in its entirety as well as sample usage in a fictional blog post component. Thanks for reading!

useVisibility.js
1
import { useState } from "react"
2
3
const useVisibility = (defaultVisibility = false) => {
4
const [visibility, setVisibility] = useState(defaultVisibility)
5
6
const handleVisibility = value => {
7
if (value && typeof value === "boolean") {
8
setVisibility(value)
9
} else {
10
setVisibility(state => !state)
11
}
12
}
13
14
return [visibility, handleVisibility]
15
}
16
17
export default useVisibility
18

And here is an example usage for for a dialog component in a fictional blog post component.

Post.js
1
import React from "react"
2
import Layout from "components/Layout"
3
import Button from "components/Button"
4
import Article from "components/Article"
5
import Dialog from "components/Dialog"
6
import useVisibility from "hooks/useVisibility"
7
8
const Post = ({ data }) => {
9
const [dialogVisibility, handleDialogVisibility] = useVisibility(false)
10
11
return (
12
<Layout>
13
<Article data={data} />
14
<Button onClick={() => handleDialogVisibility(true)}>
15
Join Our Newsletter
16
</Button>
17
<Dialog
18
open={dialogVisibility}
19
onClose={() => handleDialogVisibility(false)}
20
>
21
{/* ..some sort of sign up form here */}
22
</Dialog>
23
</Layout>
24
)
25
}
26
27
export default Post
28

Interested in working together?

Drop me a line
© 2020 Lost Creek Designs