The goal of this tutorial is to teach you how to create and use Custom Hooks in React. By the end of this tutorial, you will be able to extract component logic into reusable functions and share behaviors between different components.
To fully grasp this tutorial, you need to have a basic understanding of React and JavaScript syntax, including ES6 features like arrow functions, and the use of state and effect hooks in React.
A custom Hook is essentially a JavaScript function, but its name starts with 'use', and it can call other Hooks.
Custom Hooks allow us to reuse stateful logic between components. Before Hooks were introduced, this was done via render props and higher-order components. But custom hooks provide a much easier way to share logic between components.
A custom Hook is a normal function which we've decided to call a Hook. It's a convention that our function name should begin with the word 'use'. If the function does call other Hooks, we must follow the rules of Hooks.
Let's create a custom Hook called useWindowWidth
that will return the window's width.
import { useState, useEffect } from 'react';
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return width;
}
In the above code, we've created a custom Hook that uses the useState
and useEffect
Hooks to track and update the window width.
Let's see how we can use the useWindowWidth
hook we created above in a component.
import React from 'react';
import useWindowWidth from './useWindowWidth';
function Component() {
const width = useWindowWidth();
return (
<div>
<p>Window width is: {width}</p>
</div>
);
}
export default Component;
In the code above, we imported our custom Hook and used it inside our functional component. The component will now always display the current window width, and update it whenever the window is resized.
In this tutorial, we've learned how to create and use Custom Hooks in React. We saw that Custom Hooks are a built-in feature in React that allows us to extract component logic into reusable functions. We also learned how to use the custom Hook in a React component.
Now that you understand Custom Hooks, a good next step would be to learn more about the other types of Hooks that React provides, like useContext
, useReducer
, and useMemo
.
Create a custom Hook useDocumentTitle
that sets the document title to the given input. Use it in a component to set the document title.
Create a custom Hook useLocalStorage
that syncs a value with local storage. The Hook should return the current value and a function to update it.
Solutions:
useDocumentTitle
Hook:import { useEffect } from 'react';
function useDocumentTitle(title) {
useEffect(() => {
document.title = title;
}, [title]);
}
Component usage:
import React from 'react';
import useDocumentTitle from './useDocumentTitle';
function Component() {
useDocumentTitle('My new title');
return (
<div>
<p>Check the document title!</p>
</div>
);
}
export default Component;
useLocalStorage
Hook:import { useState, useEffect } from 'react';
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});
const setValue = value => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};
return [storedValue, setValue];
}
Component usage:
import React from 'react';
import useLocalStorage from './useLocalStorage';
function Component() {
const [name, setName] = useLocalStorage('name', 'Anonymous');
return (
<div>
<input
type="text"
value={name}
onChange={e => setName(e.target.value)}
/>
</div>
);
}
export default Component;
Make sure to practice creating your own custom Hooks and using them in different components to get a good grasp of this concept. Happy coding!