Reusing Logic with Custom Hooks
React comes with several built-in Hooks like useState , useContext , and useEffect . Sometimes, you’ll wish that there was a Hook for some more specific purpose: for example, to fetch data, to keep track of whether the user is online, or to connect to a chat room. You might not find these Hooks in React, but you can create your own Hooks for your application’s needs.
You will learn
- What custom Hooks are, and how to write your own
- How to reuse logic between components
- How to name and structure your custom Hooks
- When and why to extract custom Hooks
Custom Hooks: Sharing logic between components
Imagine you’re developing an app that heavily relies on the network (as most apps do). You want to warn the user if their network connection has accidentally gone off while they were using your app. How would you go about it?
It seems like you’ll need two things in your component:
- A piece of state that tracks whether the network is online.
- An Effect that subscribes to the global online and offline events, and updates that state.
This will keep your component synchronized with the network status. You might start with something like this:
Try turning your network on and off, and notice how this StatusBar updates in response to your actions.
Now imagine you also want to use the same logic in a different component. You want to implement a Save button that will become disabled and show “Reconnecting…” instead of “Save” while the network is off.
To start, you can copy and paste the isOnline state and the Effect into SaveButton :
Verify that, if you turn off the network, the button will change its appearance.
These two components work fine, but the duplication in logic between them is unfortunate. It seems like even though they have different visual appearance, you want to reuse the logic between them.
Extracting your own custom Hook from a component
Imagine for a moment that, similar to useState and useEffect , there was a built-in useOnlineStatus Hook. Then both of these components could be simplified and you could remove the duplication between them:
Although there is no such built-in Hook, you can write it yourself. Declare a function called useOnlineStatus and move all the duplicated code into it from the components you wrote earlier:
At the end of the function, return isOnline . This lets your components read that value:
Verify that switching the network on and off updates both components.
Now your components don’t have as much repetitive logic. More importantly, the code inside them describes what they want to do (use the online status!) rather than how to do it (by subscribing to the browser events).
When you extract logic into custom Hooks, you can hide the gnarly details of how you deal with some external system or a browser API. The code of your components expresses your intent, not the implementation.
Hook names always start with use
React applications are built from components. Components are built from Hooks, whether built-in or custom. You’ll likely often use custom Hooks created by others, but occasionally you might write one yourself!
You must follow these naming conventions:
- React component names must start with a capital letter, like StatusBar and SaveButton . React components also need to return something that React knows how to display, like a piece of JSX.
- Hook names must start with use followed by a capital letter, like useState (built-in) or useOnlineStatus (custom, like earlier on the page). Hooks may return arbitrary values.
This convention guarantees that you can always look at a component and know where its state, Effects, and other React features might “hide”. For example, if you see a getColor() function call inside your component, you can be sure that it can’t possibly contain React state inside because its name doesn’t start with use . However, a function call like useOnlineStatus() will most likely contain calls to other Hooks inside!
If your linter is configured for React, it will enforce this naming convention. Scroll up to the sandbox above and rename useOnlineStatus to getOnlineStatus . Notice that the linter won’t allow you to call useState or useEffect inside of it anymore. Only Hooks and components can call other Hooks!
Should all functions called during rendering start with the use prefix?
No. Functions that don’t call Hooks don’t need to be Hooks.
If your function doesn’t call any Hooks, avoid the use prefix. Instead, write it as a regular function without the use prefix. For example, useSorted below doesn’t call Hooks, so call it getSorted instead:
This ensures that your code can call this regular function anywhere, including conditions:
You should give use prefix to a function (and thus make it a Hook) if it uses at least one Hook inside of it:
Technically, this isn’t enforced by React. In principle, you could make a Hook that doesn’t call other Hooks. This is often confusing and limiting so it’s best to avoid that pattern. However, there may be rare cases where it is helpful. For example, maybe your function doesn’t use any Hooks right now, but you plan to add some Hook calls to it in the future. Then it makes sense to name it with the use prefix:
Then components won’t be able to call it conditionally. This will become important when you actually add Hook calls inside. If you don’t plan to use Hooks inside it (now or later), don’t make it a Hook.
Custom Hooks let you share stateful logic, not state itself
In the earlier example, when you turned the network on and off, both components updated together. However, it’s wrong to think that a single isOnline state variable is shared between them. Look at this code:
It works the same way as before you extracted the duplication:
These are two completely independent state variables and Effects! They only happened to have the same value at the same time because you synchronized them with the same external value (whether the network is on).
To better illustrate this, we’ll need a different example. Consider this Form component:
There’s some repetitive logic for each form field:
- There’s a piece of state ( firstName and lastName ).
- There’s a change handler ( handleFirstNameChange and handleLastNameChange ).
- There’s a piece of JSX that specifies the value and onChange attributes for that input.
You can extract the repetitive logic into this useFormInput custom Hook:
Notice that it only declares one state variable called value .
However, the Form component calls useFormInput two times:
This is why it works like declaring two separate state variables!
Custom Hooks let you share stateful logic but not state itself. Each call to a Hook is completely independent from every other call to the same Hook. This is why the two sandboxes above are completely equivalent. If you’d like, scroll back up and compare them. The behavior before and after extracting a custom Hook is identical.
When you need to share the state itself between multiple components, lift it up and pass it down instead.
Passing reactive values between Hooks
The code inside your custom Hooks will re-run during every re-render of your component. This is why, like components, custom Hooks need to be pure. Think of custom Hooks’ code as part of your component’s body!
Because custom Hooks re-render together with your component, they always receive the latest props and state. To see what this means, consider this chat room example. Change the server URL or the selected chat room:
When you change serverUrl or roomId , the Effect “reacts” to your changes and re-synchronizes. You can tell by the console messages that the chat re-connects every time that you change your Effect’s dependencies.
Now move the Effect’s code into a custom Hook:
This lets your ChatRoom component call your custom Hook without worrying about how it works inside:
This looks much simpler! (But it does the same thing.)
Notice that the logic still responds to prop and state changes. Try editing the server URL or the selected room:
Notice how you’re taking the return value of one Hook:
and pass it as an input to another Hook:
Every time your ChatRoom component re-renders, it passes the latest roomId and serverUrl to your Hook. This is why your Effect re-connects to the chat whenever their values are different after a re-render. (If you ever worked with music processing software, chaining Hooks like this might remind you of chaining multiple audio effects, like adding reverb or chorus. It’s as if the output of useState “feeds into” the input of the useChatRoom .)
Passing event handlers to custom Hooks
This section describes an experimental API that has not yet been added to React, so you can’t use it yet.
As you start using useChatRoom in more components, you might want to let different components customize its behavior. For example, currently, the logic for what to do when a message arrives is hardcoded inside the Hook:
Let’s say you want to move this logic back to your component:
To make this work, change your custom Hook to take onReceiveMessage as one of its named options:
This will work, but there’s one more improvement you can do when your custom Hook accepts event handlers.
Adding a dependency on onReceiveMessage is not ideal because it will cause the chat to re-connect every time the component re-renders. Wrap this event handler into an Effect Event to remove it from the dependencies:
Now the chat won’t re-connect every time that the ChatRoom component re-renders. Here is a fully working demo of passing an event handler to a custom Hook that you can play with:
Notice how you no longer need to know how useChatRoom works in order to use it. You could add it to any other component, pass any other options, and it would work the same way. That’s the power of custom Hooks.
When to use custom Hooks
You don’t need to extract a custom Hook for every little duplicated bit of code. Some duplication is fine. For example, extracting a useFormInput Hook to wrap a single useState call like earlier is probably unnecessary.
However, whenever you write an Effect, consider whether it would be clearer to also wrap it in a custom Hook. You shouldn’t need Effects very often, so if you’re writing one, it means that you need to “step outside React” to synchronize with some external system or to do something that React doesn’t have a built-in API for. Wrapping your Effect into a custom Hook lets you precisely communicate your intent and how the data flows through it.
For example, consider a ShippingForm component that displays two dropdowns: one shows the list of cities, and another shows the list of areas in the selected city. You might start with some code that looks like this:
Although this code is quite repetitive, it’s correct to keep these Effects separate from each other. They synchronize two different things, so you shouldn’t merge them into one Effect. Instead, you can simplify the ShippingForm component above by extracting the common logic between them into your own useData Hook:
Now you can replace both Effects in the ShippingForm components with calls to useData :
Extracting a custom Hook makes the data flow explicit. You feed the url in and you get the data out. By “hiding” your Effect inside useData , you also prevent someone working on the ShippingForm component from adding unnecessary dependencies to it. Ideally, with time, most of your app’s Effects will be in custom Hooks.
Keep your custom Hooks focused on concrete high-level use cases
Start by choosing your custom Hook’s name. If you struggle to pick a clear name, it might mean that your Effect is too coupled to the rest of your component’s logic, and is not yet ready to be extracted.
Ideally, your custom Hook’s name should be clear enough that even a person who doesn’t write code often could have a good guess about what your custom Hook does, what it takes, and what it returns:
- ✅ useData(url)
- ✅ useImpressionLog(eventName, extraData)
- ✅ useChatRoom(options)
When you synchronize with an external system, your custom Hook name may be more technical and use jargon specific to that system. It’s good as long as it would be clear to a person familiar with that system:
- ✅ useMediaQuery(query)
- ✅ useSocket(url)
- ✅ useIntersectionObserver(ref, options)
Keep custom Hooks focused on concrete high-level use cases. Avoid creating and using custom “lifecycle” Hooks that act as alternatives and convenience wrappers for the useEffect API itself:
- 🔴 useMount(fn)
- 🔴 useEffectOnce(fn)
- 🔴 useUpdateEffect(fn)
For example, this useMount Hook tries to ensure some code only runs “on mount”:
Custom “lifecycle” Hooks like useMount don’t fit well into the React paradigm. For example, this code example has a mistake (it doesn’t “react” to roomId or serverUrl changes), but the linter won’t warn you about it because the linter only checks direct useEffect calls. It won’t know about your Hook.
If you’re writing an Effect, start by using the React API directly:
Then, you can (but don’t have to) extract custom Hooks for different high-level use cases:
A good custom Hook makes the calling code more declarative by constraining what it does. For example, useChatRoom(options) can only connect to the chat room, while useImpressionLog(eventName, extraData) can only send an impression log to the analytics. If your custom Hook API doesn’t constrain the use cases and is very abstract, in the long run it’s likely to introduce more problems than it solves.
Custom Hooks help you migrate to better patterns
Effects are an “escape hatch” : you use them when you need to “step outside React” and when there is no better built-in solution for your use case. With time, the React team’s goal is to reduce the number of the Effects in your app to the minimum by providing more specific solutions to more specific problems. Wrapping Effects in custom Hooks makes it easier to upgrade your code when these solutions become available. Let’s return to this example:
In the above example, useOnlineStatus is implemented with a pair of useState and useEffect . However, this isn’t the best possible solution. There is a number of edge cases it doesn’t consider. For example, it assumes that when the component mounts, isOnline is already true , but this may be wrong if the network already went offline. You can use the browser navigator.onLine API to check for that, but using it directly would break if you run your React app on the server to generate the initial HTML. In short, this code could be improved.
Luckily, React 18 includes a dedicated API called useSyncExternalStore which takes care of all of these problems for you. Here is how your useOnlineStatus Hook, rewritten to take advantage of this new API:
Notice how you didn’t need to change any of the components to make this migration:
This is another reason for why wrapping Effects in custom Hooks is often beneficial:
- You make the data flow to and from your Effects very explicit.
- You let your components focus on the intent rather than on the exact implementation of your Effects.
- When React adds new features, you can remove those Effects without changing any of your components.
Similar to a design system, you might find it helpful to start extracting common idioms from your app’s components into custom Hooks. This will keep your components’ code focused on the intent, and let you avoid writing raw Effects very often. There are also many excellent custom Hooks maintained by the React community.
Will React provide any built-in solution for data fetching?
We’re still working out the details, but we expect that in the future, you’ll write data fetching like this:
If you use custom Hooks like useData above in your app, it will require fewer changes to migrate to the eventually recommended approach than if you write raw Effects in every component manually. However, the old approach will still work fine, so if you feel happy writing raw Effects, you can continue to do that.
There is more than one way to do it
Let’s say you want to implement a fade-in animation from scratch using the browser requestAnimationFrame API. You might start with an Effect that sets up an animation loop. During each frame of the animation, you could change the opacity of the DOM node you hold in a ref until it reaches 1 . Your code might start like this:
To make the component more readable, you might extract the logic into a useFadeIn custom Hook:
You could keep the useFadeIn code as is, but you could also refactor it more. For example, you could extract the logic for setting up the animation loop out of useFadeIn into a new custom Hook called useAnimationLoop :
Effects let you connect React to external systems. The more coordination between Effects is needed (for example, to chain multiple animations), the more it makes sense to extract that logic out of Effects and Hooks completely like in the sandbox above. Then, the code you extracted becomes the “external system”. This lets your Effects stay simple because they only need to send messages to the system you’ve moved outside React.
Sometimes, you don’t even need a Hook!
- Custom Hooks let you share logic between components.
- Custom Hooks must be named starting with use followed by a capital letter.
- Custom Hooks only share stateful logic, not state itself.
- You can pass reactive values from one Hook to another, and they stay up-to-date.
- All Hooks re-run every time your component re-renders.
- The code of your custom Hooks should be pure, like your component’s code.
- Wrap event handlers received by custom Hooks into Effect Events.
- Don’t create custom Hooks like useMount . Keep their purpose specific.
- It’s up to you how and where to choose the boundaries of your code.
Try out some challenges
Challenge 1 of 5 : extract a usecounter hook.
This component uses a state variable and an Effect to display a number that increments every second. Extract this logic into a custom Hook called useCounter . Your goal is to make the Counter component implementation look exactly like this:
You’ll need to write your custom Hook in useCounter.js and import it into the Counter.js file.
How do you like these docs?
How to Build Your Own React Hooks: A Step-by-Step Guide
Custom React hooks are an essential tool that let you add special, unique functionality to your React applications.
In many cases, if you want to add a certain feature to your application, you can simply install a third-party library that is made to solve your problem. But if such a library or hook doesn't exist, what do you do?
As a React developer, it's important to learn the process of creating custom hooks to solve problems or add missing features within your own React projects.
In this step-by-step guide, I will show you how to create your own custom React hooks by breaking down three hooks I've made for my own applications, along with what problems they were created to solve.
1. useCopyToClipboard Hook
On a past version of my website, reedbarger.com , I allowed users to copy code from my articles with the help of a package called react-copy-to-clipboard .
A user just hovers over the snippet, clicks the clipboard button, and the code is added to their computer's clipboard to enable them to paste and use the code, wherever they like.
Instead of using a third party library, however, I wanted to recreate this functionality with my own custom React hook. As with every custom react hook I create, I put it a dedicated folder, usually called utils or lib , specifically for functions that I can reuse across my app.
We'll put this hook in a file called useCopyToClipboard.js and I'll make a function of the same name.
There are various ways that we can copy some text to the user's clipboard. I prefer to use a library for this, which makes the process more reliable, called copy-to-clipboard .
It exports a function, which we will call copy .
Next we will create a function that will be used for copying whatever text wants to be added to the user's clipboard. We will call this function handleCopy .
How to make the handleCopy function
Within the function, we first need to make sure it only accepts data that is of type string or number. We will set up an if-else statement, which will make sure that the type is either the string or number. Else, we will log an error to the console that tells the user you cannot copy any other types.
Next we take the text and convert it to a string, which we will then pass to the copy function. From there, we return the handleCopy function from the hook to wherever we like in our application.
Generally, the handleCopy function will be connected to an onClick of a button.
Additionally, we want some state that represents whether the text was copied or not. To create that, we will call useState at the top of our hook and make a new state variable isCopied , where the setter will be called setCopy .
Initially this value will be false. If the text is successfully copied, we will set copy to true. Else, we will set it to false.
Finally, we will return isCopied from the hook within an array along with handleCopy .
How to use useCopyToClipboard
We can now use useCopyToClipboard within any component that we like.
In my case I will use it with a copy button component which received the code for our code snippet.
To make this work, all we need to do is add an on click to the button. And in the return of a function called handle copy with the code asked to it as text. And once it's copied it's true. We can show a different icon indicating a copy was successful.
How to add a reset interval
There's one improvement we can make to our code. As we've currently written our hook, isCopied will always be true, meaning we will always see the success icon:
If we want to reset our state after a few seconds you can pass a time interval to useCopyToClipboard . Let's add that functionality.
Back in our hook, we can create a parameter called resetInterval , whose default value is null , which will ensure that the state will not reset if no argument is passed to it.
We will then add useEffect to say that if the text is copied and we have a reset interval, we will set isCopied back to false after that interval using a setTimeout .
Additionally, we need to clear that timeout if our component that the hook is being used in unmounts (meaning our state is no longer there to update).
Finally, the last improvement we can make is to wrap handleCopy in the useCallback hook in order to ensure that it will not be recreated every time there is a rerender.
And with that, we have our final hook which allows the state to be reset after a given time interval. If we pass one to it, we should see a result like what we have below.
2. usePageBottom Hook
In React apps, sometimes it is important to know when your user has scrolled to the bottom of a page.
In apps where you have an infinite scroll, such as Instagram for example, once the user hits the bottom of the page, you need to fetch more posts.
Let’s take a look at how to create a usePageBottom hook ourselves for similar use cases like creating an infinite scroll.
We’ll begin by making a separate file, usePageBottom.js, in our utils folder and we'll add a function (hook) with the same name:
Next, we’ll need to calculate when our user hits the bottom of the page. We can determine this with information from the window . In order to access this, we’re going to need to make sure our component that the hook is called within is mounted, so we’ll use the useEffect hook with an empty dependencies array.
The user will have scrolled to the bottom of the page when the window’s innerHeight value plus the document’s scrollTop value is equal to the offsetHeight . If those two values are equal, the result will be true, and the user has scrolled to the bottom of the page:
We’ll store the result of this expression in a variable, isBottom and we’ll update a state variable called bottom , which we’ll ultimately return from our hook.
Our code as is, however, won’t work. Why not?
The issue lies in the fact that we need to calculate isBottom whenever the user is scrolling. As a result, we need to listen for a scroll event with window.addEventListener . We can reevaluate this expression by creating a local function to be called whenever the user scrolls, called handleScroll .
Finally, since we have an event listener that is updating state, we need to handle the event that our user navigates away from the page and our component is removed. We need to remove the scroll event listener that we added, so we don’t attempt to update a state variable that no longer exists.
We can do this by returning a function from useEffect along with window.removeEventListener , where we pass a reference to the same handleScroll function. And we’re done.
Now we can simply call this code in any function where we want to know whether we’ve hit the bottom of the page or not.
Within my Gatsby site, I have a header, and as I decrease the size of the page, I want to show fewer links.
To do this we could use a media query (CSS), or we could use a custom React hook to give us the current size of the page and hide or show the links in our JSX.
Previously, I was using a hook from the a library called react-use . Instead of bringing an entire third-party library, I decided to create my own hook that would provide the dimensions of the window, both the width and height. I called this hook useWindowSize .
How to create the hook
First, we’ll create a new file .js in our utilities (utils) folder, the same name as the hook useWindowSize . I’ll import React (to use hooks) while exporting the custom hook.
Now since I’m using this within a Gatsby site, which is server-rendered, I need to get the size of the window. But we may not have access to it because we’re on the server.
To check and make sure we’re not on the server, we can see if type of window is not equal to the string undefined .
In which case we can return to a default width and height for a browser, say, 1200 and 800 within an object:
How to get the width and height from window
And assuming we are on the client and can get the window, we can take the useEffect hook to perform a side effect by interacting with window . We’ll include an empty dependencies array to make sure the effect function is called only once the component (that this hook is called in) is mounted.
To find out the window width and height, we can add an event listener and listen for the resize event. And whenever the browser sizes changes, we can update a piece of state (created with useState ), which we’ll call windowSize , and the setter to update it will be setWindowSize .
When the window is resized, the callback will be called and the windowSize state will be updated with the current window dimensions. To get that, we set the width to window.innerWidth , and height to window.innerHeight .
How to add SSR support
However, the code as we have it here will not work. This is because a key rule of hooks is that they cannot be called conditionally. As a result, we cannot have a conditional above our useState or useEffect hook before they are called.
So to fix this, we’ll set the initial value of useState conditionally. We’ll create a variable called isSSR , which will perform the same check to see if the window is not equal to the string undefined .
And we’ll use a ternary to set the width and height by first checking to see if we’re on the server. If we are we’ll use the default value, and if not, we’ll use window.innerWidth and window.innerHeight .
Then, finally, we need to think about when our components unmount. What do we need to do? We need to remove our resize listener.
How to remove the resize event listener
You can do that by returning a function from useEffectand. We will remove the listener with window.removeEventListener .
But we need a reference to the same function, not two different ones as we have here. To do that, we’ll create a shared callback function to both of the listeners called changeWindowSize .
And finally, at the end of the hook, we will return our windowSize state. And that’s it.
To use the hook, we just need to import it where we need it, call it, and use the width wherever we want to hide or show certain elements.
In my case, this is at the 500px mark. There, I want to hide all of the other links and only show the Join Now button, like you see in the example above:
This hook will work on any server-rendered React app, such as Gatsby and Next.js.
3. useDeviceDetect Hook
I’m in the process of building a new landing page for a course of mine, and I experienced a very strange error on mobile devices. On desktop computers, the styles looked great.
But when I looked at on mobile, everything was out of place and broken.
I tracked the problem down to one library called react-device-detect which I was using to detect whether users had a mobile device or not. If so, I would remove the header.
The problem was that this library doesn’t have support for server-side rendering, which is what Gatsby uses by default. So I needed to create my own solution to check when a user was on a mobile device. And for that, I decided to make a custom hook with the name useDeviceDetect .
How I created the Hook
How to get the user agent from window
The way that we can make sure whether we can get information about the user’s device is through the userAgent property (located on the navigator property of window).
And since interacting with the window API as an API / external resource would be classed as a side effect, we need to get access to the user agent within the useEffect hook.
Once the component mounts, we can use typeof navigator to determine if we are on the client or server. If we’re on the server, we won’t have access to the window. typeof navigator will be equal to the string undefined since it’s not there. Otherwise, if we’re on the client, we’ll be able to get our user agent property.
We can express all this using a ternary to get the userAgent data:
How to check if userAgent is a mobile device
userAgent is a string value which will be set to any one of the following device names if they are using a mobile device:
Android, BlackBerry, iPhone, iPad, iPod, Opera Mini, IEMobile, or WPDesktop.
All we have to do is take the string we get and use the .match() method with a regex to see whether it’s any one of these strings. We’ll store it in a local variable called mobile .
We’ll store the result in state with the useState hook, which we’ll give an initial value of false. For it, we’ll create a corresponding state variable isMobile , and the setter will be setMobile .
So once we get the mobile value we will set it in state. Then finally we will return an object from the hook so we can add more values in the future if we want to choose to add more functionality to this hook.
Within the object, we’ll add isMobile as a property and value:
Back in the landing page we can execute the hook and simply get that property from the destructured object and use it where we need it.
As I've attempted to illustrate through each of these examples, custom React hooks can give us the tools to fix our own problems when third-party libraries fall short.
I hope that this guide has given you a better idea of when and how to create your own React hooks. Feel free to use any of these hooks and above code in your own projects and as the inspiration for your own custom React hooks.
Enjoy this post? Join The React Bootcamp
The React Bootcamp takes everything you should know about learning React and bundles it into one comprehensive package, including videos, cheatsheets, plus special bonuses.
Gain the insider information hundreds of developers have already used to master React, find their dream jobs, and take control of their future:
React developer who loves to make incredible apps.
If this article was helpful, tweet it .
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started
Posted on Jan 30, 2021
Why You Should Be Writing React Custom Hooks
You’re probably familiar with built-in React hooks like useEffect and useState. But have you explored writing custom hooks? Or thought about why you would want to?
“No, why would I?” You might ask. And since you’re playing along so kindly, I’ll tell you!
Custom hooks are a handy way to encapsulate hook-related logic that can be re-used across components when using component composition isn’t really something that will help, make sense, or just "look" semantically right.
Think of a custom hook as a super-powered helper function. According to the rules of hooks , you can't call a hook (like useEffect) in an ordinary helper function that is declared outside of a component. But you can call hooks inside custom hooks!
Additionally, if you have a component in which you have two or more separate pieces of useEffect logic going on, you might want to consider putting them into custom hooks to separate and name them, even if this isn’t logic that will be shared by any other component.
This is much like encapsulating logic into a well-named function for the sake of readability and code organization. After all, it’s a bit tough to read a string of useEffect routines and understand what’s going on. But if, on the other hand, you have one called something like useSyncCustomerRecordStore, then your consumer code is that much more readable.
The difference between a custom hook and a component is that a custom hook will return values, not React components or markup. In this way, they’re sort of like component helpers.
The Shape Of A Custom Hook
- Functions whose names begin with 'use...'
- Functions which can call other hooks
A simple custom hook might look like this:
Example: Page Data
I’m currently working on an enterprise application suite realized in the form of micro-service applications. To the user, it seems like one large application, but really, under the hood, it’s a collection of several independent React apps.
These apps need to refer to each others’ pages with links and common titles, and that data — called pageData — is set up in a context provider so that any component at any level in the apps can access it with a useContext hook.
Now, it is pretty simple to use this data without writing a custom hook. All a consumer component has to do is import the PageDataContext and then call useContext on it, like this:
Okay, So Why Use A Custom Hook For This?
Okay, so that's pretty simple, right? It's only three lines of code: two import statements, and a call to useContext. In that case, why am I still recommending a custom hook for a situation like this?
Here are a few reasons, from least to most important:
Eliminating Boilerplate Adds Up
If you just look at this one example, I'm only eliminating one line of boilerplate, because I will still have to import my custom hook, usePageData. I only really eliminate the line that imports useContext.
So what's the big deal? The thing is, just about every page in my enterprise app suite needs to use this pageData object, so we're talking hundreds of components. If we eliminate even one line of boilerplate from each one, we're talking hundreds of lines.
And believe me, just writing that extra line every time I create a new page feels that much more annoying, so there's a sort of pscychological/motivational benefit that adds up over time, too.
If you've used hooks like useEffect much in your code, you've probably come across situations where there are two or three pieces of useEffect logic (either in separate calls to useEffect, or combined into one). This quickly gets hard to take in when you're reading the code.
If you're like me, you wind up putting comments about each piece of useEffect logic, such as:
But one of the fundamental concepts of readable code is noticing where you're writing blocks of comments in big dumping ground "main" type functions, and instead separating those pieces of logic into their own, individual, well-named functions. Another developer reading your code is going to have a much easier time taking it all in when these details are abstracted away from the big picture. But when they're ready to drill into detail, they can go look at the function declaration.
The same is true of custom hooks. If I see this in the component code, I have a pretty good idea of what is going on:
I've saved the most important reason for last, and that's that it is good to encapsulate the logic in one place. Sure it's only two lines of code, but what if we decide to store pageData in a Redux or Mobx store instead of React Context?
If we're already using a custom hook, no problem! We just change the internal code in the hook and return the same pageData object back to the consumer code. What we don't have to do is go and update hundreds of components to import, say, useSelector, and then call it instead of useContext.
What useGetPageData Looks Like
It's dead simple! Just:
Other Things You Can Do With Custom Hooks
Top comments (5)
Templates let you quickly answer FAQs or store snippets for re-use.
- Work Senior Front End Engineer
- Joined Mar 29, 2022
You have mentioned, you can't call a hook (like useEffect) in an ordinary helper function that is declared outside of a component
But we can call hook in any Plain JS function rite
- Location Ghana
- Education University of Ghana, Legon
- Work A teacher and a web application developer
- Joined Sep 11, 2021
- Joined Mar 12, 2019
a custom hook can return React component or markup
- Joined Jul 20, 2021
Short and clearly. Thank you.
Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .
Hide child comments as well
For further actions, you may consider blocking this person and/or reporting abuse
- What's a billboard?
- Manage preferences
Visualizing Promises and Async/Await 🤯
☝️ Check out this all-time classic DEV post
Notion UI React
Bogdan Aksenov - Feb 26
Tapajyoti Bose - Feb 19
7 React UI Component Libraries for Building Beautiful Interfaces
Suraj Vishwakarma - Feb 27
Learn Nuxt 3 — Full course for beginners [3 hours] 2023
Guillaume Duhan - Feb 10
Once suspended, sevenzark will not be able to comment or publish posts until their suspension is removed.
Once unsuspended, sevenzark will be able to comment and publish posts again.
Once unpublished, all posts by sevenzark will become hidden and only accessible to themselves.
If sevenzark is not suspended, they can still re-publish their posts from their dashboard.
Once unpublished, this post will become invisible to the public and only accessible to Dave M.
They can still re-publish the post if they are not suspended.
Thanks for keeping DEV Community safe. Here is what you can do to flag sevenzark:
sevenzark consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy.
Unflagging sevenzark will restore default visibility to their posts.
We're a place where coders share, stay up-to-date and grow their careers.
Bits and Pieces
Mar 25, 2019
Writing Your Own Custom React Hooks
Let’s extract your components logic into reusable functions..
It’s a scary world out there and please don’t tell me you are planning to survive this React World just with the help of classes (of course you can but it will be painful). Hooks are the new trend in React Community and are inevitable for any React developer out there.
Hooks basically put your functions on steroids so that you can stop relying on classes and move on to functions (if you prefer classes over functions then it’s a different story). Hooks will revolutionize how the React code is to be written. Sooner or later, you will have to dive into hooks.
This post is for devs who know what hooks are and have used them before. If you still haven’t touched it then it’s time you do.
Understanding Hooks in React
An introduction to react 16.7 hooks, with examples..
React Hooks: Beyond useState & useEffect
Take a step further and learn usereducer, useref, usecontext, and usememo..
Useful tip: Use Bit to encapsulate components with all their dependencies and setup. Build truly modular applications with better code reuse, simpler maintenance and less overhead.
Share reusable code components as a team · Bit
Easily share reusable components between projects and applications to build faster as a team. collaborate to develop…, custom hooks.
There might be instances where you have been using the same repetitive and redundant stateful logic inside multiple components. We were able to handle this situation by relying on Render props and Higher Order Components. But with hooks, we can do it in a much simpler and cleaner way, Thanks to the Custom hooks.
Okay, But what are they?
Let’s say you have 2 functions (components) which implement some common logic. You can create a third function with this common logic and implement it in the other two functions. After all, hooks are just functions.
Custom hooks means fewer keystrokes and less repetitive code.
Cool, But why it’s high time to write our own custom hooks?
Yeah, so before you start writing your own custom hooks there is a VERY high possibility that someone has already written it and put it on npm. So if you are doing something new it’s probably not new anymore.
You must have heard about Kent C. Dodds , he is a pretty big deal in React community and I quote the statement he made on his youtube channel during December when hooks were not stable (now they are).
“hooks are not stable, but by the time they are, every hook conceivable will have been written and open sourced already… I’m pretty sure there are at least 10 localstorage hooks on npm already.”
You kidding, right? A minimum of 10 hooks just based on localStorage!! Guys take a break 🙄.
So if you are serious about doing something cool and awesome with hooks, better start now .
This post doesn’t provide you with innovative ideas for writing your own custom hooks but teaches you how to write or build custom hooks by giving some examples.
Let’s jump into some of these examples.
Say we have to build a component which on every click increases the count and updates the title of the page with the count value using hooks. Not a big deal, right.
It works well. I always prefer creating the component first and then extracting out the stateful logic from that function(component) and then putting it into another function(custom hook) and then just doing some refactoring so the component works well with our hook.
Let’s take the useEffect section out of the component and put it inside our new function useDocumentTitle .
Simple, but not useful? Where can this be useful?
To show unread messages or notifications on slack or facebook. We can use this useDocumentTitle hook in a place where we get the message and then we call this hook with a count of unread messages and title.
Building a Counter component that stores the count in local storage and updates and gets the count value from localStorage.
Get the value from local storage, if it doesn’t exist set it to 0. Update the value on every click in local storage. It is nice but let’s say you have to build another Counter component which increases the value by 5 or the value increase every second. You might find yourself re-writing the localStorage code in every component. Let’s avoid this and write our own custom hook.
useLocalStorageState takes two parameters, one being the key and second the default value. We get the count from localStorage and set it to state . We use the useEffect hook to set the value in the local storage and finally return out the state and setState method as an array.
Now, this looks better, you just have to call the hook with the key and a default value. And the key to localStorage is added with the default value and fetched by our hook while the count is updated by the component itself. We put local storage code in our hook and the state updating part in our component.
You encountered this problem where you have to create a component to display some images from Unsplash and make another component which is an Unsplash image slider. In these two components, there exists a common stateful logic of getting the images from the API. We can extract this logic in our custom hook useUnSplashImages .
In this hook, we take the secret key and query as parameters. We have three states to worry about loading, error and response data. We make a GET request using axios with the URL and update the state based on response and return an array of our three states which can be destructured in the respective component.
And below is how we implement it our component->
Our custom hook does the fetching and provides us with the images array, loading status and also with an error status. Remaining logic is handled by the component, we just have to provide the query and the secret key provided by Unsplash. Our component receives the three states and uses them as required. Later on, we can create a slider or loop through the images array to display the images.
I found this hook to be super useful and helps you carry out all the array related tasks easily. Building a todo list was never this easy.
This custom hook is beautiful and easy to comprehend. This hook takes the initial array as a parameter and provides the methods to modify it. add adds an element to the existing array, clear empties the array and there are much more methods like these.
Let’s implement this hook in the component:
We get the array methods object in the todos variable. We have a button which on click has the todos.add method that adds a random number in the array. In the same fashion, all the other methods are implemented.
See, it’s a beautiful hook created by Kitze .
You can take this hook or any other custom hook to a whole new level with your imagination. It’s much easy and cleaner than render props and HOC.
In this article, we learned about some cool stuff related to React’s Custom Hooks. Building these hooks seems like an art to me. Hope you liked this article and learned something new and if you did clap your heart out and follow me for more content on Medium and as well as on Twitter . Please feel free to comment and ask anything. Thanks for reading 🙏 💖.
5 Tools for Faster Development in React
5 tools to speed the development of your react application, focusing on components., 11 react ui component libraries you should know in 2019, 11 react component libraries with great components for building your next app’s ui interface in 2019., how to write better code in react, 9 useful tips for writing better code in react: learn about linting, proptypes, purecomponent and more., more from bits and pieces.
About Help Terms Privacy
Get the Medium app
JS | React | Vue | Node❤️. [email protected]
Text to speech
How to Write a Hook to Captivate Your Readers
The art of the hook is a vital component in the realm of essay writing. But what is a hook?
A hook is typically the first one or two sentences of an essay or article that is designed to grab the reader’s attention. Much like a fish gets literally hooked by bait, the hook of an essay should captivate your audience and make them want to read more.
Catch your reader's eye Grammarly can help make your writing shine Write with Grammarly
But knowing how to write a hook for an essay is a tough skill to acquire. For one, the vast amount of content out there—tweets, blogs , articles, emails, and more—make it challenging to compete for readers’ attention.
Moreover, people get distracted easily, and if you don’t hook them quickly, you might lose them.
Knowing how to write a good hook is an essential part of effective essay writing . By exploring the most common types of essay hooks, you can learn how to best engage audiences from the very beginning and develop a hook that’s right for your paper.
5 examples of essay hooks
1 statistic hook.
The statistic hook gives your audience a true and hard fact to latch onto from the get-go. Gaining your reader’s trust through expertise early on will help reinforce the points you make in the rest of your argument. Plus, a striking statistic can make your audience instantly interested in the topic at hand, motivating them to keep reading and learn more.
For example, if you’re writing a research essay about the link between sleep and stress, you can begin with a powerful statistic from the American Psychological Association like this one:
“According to a recent survey by the American Psychological Association, 43 percent of adults claim that stress has caused them to lie awake at night in the past month.”
2 Quotation hook
If you choose a memorable quotation that directly connects to what you’re writing about, the words will do the attention-grabbing work for you. Just make sure to attribute and explain the quotation after you include it so that the reader isn’t confused. And most importantly, the quotation you choose should add to the credibility and richness of your argument, rather than seeming like a random or one-off statement.
If you’re writing a literary essay about resiliency in Maya Angelou’s poetry, you might start off in this way:
“Maya Angelou once said, ‘Stand up straight and realize who you are, that you tower over your circumstances.’”
3 Anecdotal hook
Depending on the nature of your essay or article, anecdotal hooks can make for an intimate opening that tells your reader more about you. Though it’s not typical to write an essay in the first person , there are some times when you can make an exception, like in a narrative essay . This type of hook can be a little longer than others; just make sure that its length is relative to the rest of your essay.
If you’re writing about the differences between British and American baking, you might discuss an experience you had on a trip to London at the start of the essay:
“ When I first arrived in London, I was ravenous. I headed to a cafe just outside of the hotel to test out some of the local flavors and ordered a pot of tea, a scone, and pudding. But when the pudding arrived, I was surprised not to find a sweet, chocolatey custard. Instead, this pudding was made from something I’d never encountered before: mutton fat.”
4 Question hook
Posing a question at the start of a piece will immediately capture the reader’s attention and leave them wanting more. Make sure the question is open-ended. You want to make sure you’re giving the reader something to explore further, rather than asking them a simple yes or no question. People are naturally inquisitive, so give them something good to chew on.
An essay about dog psychology might begin with a question similar to this:
“ What is the difference between a well-adjusted dog and an anxious one? For starters, owners that encourage their dog’s excitement can make anxiety seem like a behavior that’s rewarded.”
5 Statement hook
Kicking off your essay with a solid declaration of your argument or position is another smart way to hook the reader. Even if they don’t agree fully with your statement, they will be intrigued to see how you support your assertion. Statement hooks often make the reader either want to argue against your view or follow along as you develop your claim.
When exploring the historical value of French cinema, you could start with a strong, declarative hook like this one:
“ French cinema is the most influential genre of film in the last 100 years and has singlehandedly shaped modern cinema as we know it.”
A great hook will not only get your reader’s attention, but it will build toward your thesis and give your reader an idea of the essay they’re about to read. Any of these options, done well, can make your essay start strong and stand out.
You can write custom Hooks that cover a wide range of use cases like form handling, animation, declarative subscriptions, timers, and probably many more we haven’t considered. What’s more, you can build Hooks that are just as easy to use as React’s built-in features.
As you see, writing and using custom hooks is pretty easy and straightforward. Depending on your use cases, you can write as many custom hooks as you like and then easily share them between different components of your app. So just have fun! And don't forget to wear a mask and wash your hands!
Finally, we’re ready to learn about writing your own Hooks! Custom Hooks let you combine Hooks provided by React into your own abstractions, and reuse common stateful logic between different components. Is this page useful? Edit this page
Hook names must start with use followed by a capital letter, like useState (built-in) or useOnlineStatus (custom, like earlier on the page). Hooks may return arbitrary values. This convention guarantees that you can always look at a component and know where its state, Effects, and other React features might “hide”.
Custom React hooks are an essential tool that let you add special, unique functionality to your React applications. In many cases, if you want to add a certain feature to your application, you can simply install a third-party library that is made to solve your problem.
Custom hooks are a handy way to encapsulate hook-related logic that can be re-used across components when using component composition isn’t really something that will help, make sense, or just "look" semantically right. Think of a custom hook as a super-powered helper function.
This custom hook is beautiful and easy to comprehend. This hook takes the initial array as a parameter and provides the methods to modify it. add adds an element to the existing array, clear empties the array and there are much more methods like these.
By exploring the most common types of essay hooks, you can learn how to best engage audiences from the very beginning and develop a hook that’s right for your paper. 5 examples of essay hooks 1 Statistic hook. The statistic hook gives your audience a true and hard fact to latch onto from the get-go.