Quick Introduction to React Custom Hooks With Dropdown Selection
mogwai
Posted on February 16, 2020
Who’s this article for?
For people new to React, and for people who have some experience with React who - like me - become confused when they have to build their own (or read others’) custom hooks. I’ll explain this as simply as I wish it was explained to me.
Skip this if you already understand the basic philosophy of React Hooks. Everyone else, start here:
As if oft drummed into our heads, React is an unopinionated Library that we use to choreograph the front-end. A very important rookie question you have to ask early enough is "why do I need this complicated thing called React when I can just build my front-end using HTML and CSS?”
I think this question is important to ask because it allows you understand the value of React, which lies in something called state
.
The simplest definition of state is that it represents the ‘status’ of data passing through a component. React updates the DOM when state changes, and this is something HTML and CSS alone are not equipped for.
Imagine you had a chat app, and you wanted to indicate, with a small ‘status’ icon (usually a tiny cicle) when they are online (green!) or offline (gray!). How would you do that?
In React, you can do this using something called Hooks. Hooks use ‘events’ to update state. If you spoke to the React hook known as useState, this is how the conversation would go:
useState: 'Hello, I'm a React Hook called useState! My job is to keep track of state changes in your React app and update everything according to your programming!"
You: "Oh, hey, useState! So I built a component that keeps track of a user's online activity and changes the color of this tiny circle."
useState: "I see. First, you have to set a default state. This is the state I'll display the circle as when nothing's happening."
You: "How about gray? For offline?"
useState: "Excellent. Works for me! Now you have to set a state setter!"
You: "state setter? What?"
useState: "Oh, it's how you teach me what to look out for to change the default state."
You: "Ah, so I tell the state-setter to watch for the user's 'last seen' status, and when it changes to 'last seen: now', to change the circle to green?"
useState: "Now you're getting it!"
That’s a crash course into hooks.
And now: Custom Hooks
The true beauty of a custom hook is that you can use it to create components that follow state-setting rules all across your application, which makes it easy to make app-wide updates without breaking anything.
Note: The following is adapted from a Frontend Masters class I took.
Imagine we wanted to create a custom hook that gives you a dropdown everytime you invoke it. Why would this be beneficial?
- It means that with one custom hook, you can create all kinds of dropdowns.
- You can have dropdowns with state tracking baked into them.
- You can reuse your dropdowns all over your application.
In code terms, instead of writing this every time you want to make a dropdown,
import React, { useState } from 'react';
const dropdownlist = ["item1", "item2", "item3"]
const FirstDropDown = () => {
const [firstdropdown, setFirstdropdown] = useState("I am the first!");
return(
<label htmlFor="First Dropdown">
First Dropdown
<select
id="first"
value={firstdropdown}
onChange={e=> setFirstdropdown(e.target.value)}
onBlur={e=> setFirstdropdown(e.target.value)}
disabled={!dropdownlist.length}>
<option>All</option>
{list.map=>(item=> <option key={item} value={item}>
{item}
</item>)}
</select>
</label>
);
};
export default FirstDropDown
you write a hook that allows you to create a state-managed custom component instead:
const Dropdownlist = () => {
return (
<label>
<FirstDropdown />
<SecondDropdown />
<ThirdDropdown />
</label>
)
};
Let’s begin!
Constructing the Hook
First, create a new jsx document for the custom hook. Keep it in the
src
folder (if you’re following the conventional setup for React projects):
file > new > useDropdown.jsx
-
Inside your new file, import React and useState:
import React, { useState } from 'react';
Note: something that used to trip me up about React hooks is that you can only use hooks inside a function. I imagine this is because it keeps the hook in local scope and prevents unwanted side effects in global.
-
Create the dropdown component that you’re going to manage with hooks:
const DropDown = (label, defaultstate, options) => {
}
The three arguments above do specific things within the dropdown component, and I’ll mention them now, but they‘ll make sense as we provide.
“Label”: Think of this as the name of the Dropdown itself. So a “Shoes” Dropdown shows a list of shoes to select, and "Shoes” is the label. In HTML, it would be represented like this:
<label htmlFor="Shoes">
Shoes
</label>
“defaultState” represents, well, the default state of the hook.
“Options” in the case of a dropdown is usually an iterable (ideally, a list) that is used to build the options the user can select from.
Makes sense? Let’s move on!
-
Define the useState hook (the state setter!)
const DropDown = (label, defaultstate, options) => { const [state, setState) = useState(defaultState); }
Now, we create the Dropdown component itself
const useDropdown = (label, defaultstate, options) => {
const [state, setState) = useState(defaultState);
const Dropdownmaker = () => (
<label htmlFor={label}>
{label}
<select>
<option>All</option>
</select>
</label>
)
}
Basically like you would a regular component.
Now it’s time to plug our state tracker.
- Plug the state tracker to auto-populate the Dropdownmaker:
const useDropdown = (label, defaultstate, options) => {
const [state, setState) = useState(defaultState);
const Dropdownmaker = () => (
<label htmlFor={label}>
{label}
<select
id={label}
value={state}
onChange={e=>setState(e.target.value)}
onBlur={e=>setState(e.target.value)}
disabled={!options.length}
>
<option>All</option>
{options.map(item=>
<option key={item} value={item}>{item}</option>)}
</select>
</label>
)
}
Now we return the necessary values for making the custom hook reusable as an array:
const useDropdown = (label, defaultstate, options) => {
const [state, setState) = useState(defaultState);
const Dropdownmaker = () => (
<label htmlFor={label}>
{label}
<select
id={label}
value={state}
onChange={e=>setState(e.target.value)}
onBlur={e=>setState(e.target.value)}
disabled={!options.length}
>
<option>All</option>
{options.map(item=>
<option key={item} value={item}>{item}</option>)}
</select>
</label>
);
return [state, Dropdownmaker, setState]
}
export default useDropdown
With that, we can now import the custom hook into components that need it!
import React from 'react';
import useDropdown from './useDropdown.jsx';
const shoe_list = ["Prada", "Jimmy Choos", "Nike", "Adidas"]
const Component = () => {
const [shoe, ShoeDropdown ] = useDropdown("Shoes", "", shoe_list);
return (
<ShoeDropdown />
)
}
Explanation
This custom hook gives you a shoe with a label of “shoes”, a default state of empty array, and an options list of “shoe_list” (which I made into an array above - although ideally you’ll be pulling from an API).
The ShoeDropdown gives you a dropdown list as we designed before, and allows you set the state, which changes the default state based on selection.
And that’s it! A quick introduction to Custom Hooks using Dropdown Selections!
Posted on February 16, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.