Best practices for naming hooks & props in React
As a developer, I think two of the most challenging things in software are (a) naming things and (b) figuring out best practices. Both of these things have many ways of accomplishing the same goal, so it's hard to know which way is recommended.
That's why I decided to make this cheat-sheet. It's a set of best practices for naming things in React. Double whammy!
🚀 How to name anything in React
Components deal with two types of data: props and state. Props get passed into a component from the function parameters and state gets created within the component's runtime.
Both props and state can contain two types of data. They can contain events and values. An easy way to distinguish between these two is that events = functions and values = variables. Take this component for example:
function Book({ title, description, author, onOpen, onClose }) { ... }
Can you identify which props are values and which are events?
title
, description
, and author
are values.
onOpen
, and onClose
are events.
Best practices for naming "data"
Now that you understand the different between data and events, let's talk about naming conventions.
Here's the general advice:
Datatype | Naming best practices | Examples ✅ |
---|---|---|
boolean | Should include a prefix like is, has etc | isVisible hasWatermark canBeProtected |
string | n/a | title , description |
number | n/a | age , contentSize |
array | Should be plural | books items activeLocations |
Best practices for naming "events"
Events have more specific best practices for their naming conventions. That's because you want them to be differentiated from data. Here's the 4 golden rules when naming events:
1. Use a prefix to indicate action
Here's an example search component:
function searchbar({ search }) { ... }
Now answer this question: Is this search prop an event or is it data?
If it was an event, it would be called like search('search term')
to get a result. If it is data, it would be the search term itself (ex. console.log(search) // 'search term'
). I'd argue, because of how we named this parameter, it's not clear whether it's an event or data.
Therefore, you should always use a prefix for events. Example: onSearch
, handleSearch
, triggerSearch
, executeSearch
etc.
search
. It takes a judgement call sometimes.2. Follow React's patterns
HTML has good practices built in. Try to follow them when you can. For example, HTML has events for things such as onclick
, onchange
, onselect
, etc. React renames these to onClick
, onChange
, onSelect
.
Try to follow these as-well. If you want an event to trigger when your component is clicked, don't name it triggerClickEvent
or onClicked
or onSelected
. Just name it either onClick
to match react, or if it needs more specifics you can name add a specifier like onItemClick
, onBookClick
, onProfileClick
.
3. Use present tense
Notice how none of HTML/react's event naming is past-tense? That's the correct way to do things. The event is happening in the present, so it should be named like that.
❌ onItemSelected
=> ✅ onItemSelect
❌ onInputChanged
=> ✅ onInputChange
❌ onResponseTriggered
=> ✅ onResponseTrigger
4. Use PascalCase
This is already common in the JavaScript ecosystem, but I thought I'd mention it anyways.
❌ oninputchange
=> ✅ onInputChange
🔥Bonus 🔥: Naming custom hooks
Here's how to properly name the custom hook, and how to format the response data.
Naming the custom hook
Once again, here's the general rules:
- Start with
use
- Use present tense
- Use pascalCase
✅ useQueryLookup
✅ useColorPicker
Naming the return value of a custom hook
Generally hooks can either return data as a single value, an array, or an object. Here's when to use all three:
Single value format
🔥 const user = useAuth()
A single value should be used when the user is only ever going to read 1 piece of data out of the hook. Typically, this is used for hooks that get their data initially from a useEffect(() => { ... }, [])
call. Or hooks where the data is passed in through a context provider.
Array value format
🔥 const [books, setBooks] = useLibrary();
Lots of react's default hooks use this array response format. This is great for hooks where the response is essentially in [data
, event
] format. If you need more events consider using object format.
Object value format
🔥 const { isOpen, onToggle, onOpen, onClose } = useModal();
Lots of custom hooks use the object format. It lets you have a larger API surface and then the consumer of the hook doesn't need to bring in every field if they don't want to.
🔥Bonus (round 2) 🔥: Naming Form Components
Form components get a specific mention because they're another area where people commonly make mistakes. Again, this is open to interpretation so if your app has a different design pattern, that's okay! This is simply the naming convention I've seen work best, so it's what I recommend.
Firstly, what's a form component? It's the kind of component that would be used in a form in your app. Here's some great examples from popular UI libraries:
Material UI – <Select />
<Select
id="demo-simple-select"
label="Age"
value={age}
onChange={handleChange}
>
...
</Select>
Chakra UI – <Input />
<Input value={value} onChange={handleChange)} />
Ant UI – <Switch />
<Switch checked={isChecked} onChange={onChange} />
As you can see, they all have slightly different API's, but they do have one thing in common:
They follow the naming convention of the component they're emulating.
That's my tip for those creating form components. If a component is going to emulate a text input component, make the controlling props be onChange
and value
. If it's going to emulate a checkbox (ex. anything that is true/false and can be flipped), give it a checked
and onChange
prop.
Want the full list? Click here for a list of the built-in HTML form components. Try to emulate their API features if you make a similar component as then it will be intuitive for your component consumers.