React Custom Hooks
React custom hooks are a way to extract, share, and reuse logic that is stateful between different components in your React application. They provide the power to reuse stateful logic without changing your component hierarchy.
What are Custom Hooks?
Custom hooks are a feature that arrived with React version 16.8 and they offer a way to extract, share, and reuse stateful logic between your components without changing your component hierarchy. Custom hooks are JavaScript functions that can use other hooks.
Here's a simple example of a custom hook:
function useCustomHook(initialValue) {
const [value, setValue] = useState(initialValue)
useEffect(() => {
// Your logic here...
}, [value])
return value
}
In this example, the function useCustomHook
is a custom hook. It takes an initialValue
as a parameter and then uses the useState
and useEffect
hooks inside of it. The useState
hook initializes the state and useEffect
executes a function based on the value of the state.
Building a Custom Hook
Building a custom hook in React involves creating a function that uses pre-existing hooks. This function can then be imported and used in other components. Let's create a custom hook named useLocalStorage
that synchronizes state with local storage.
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
}
})
useEffect(() => {
window.localStorage.setItem(key, JSON.stringify(storedValue))
}, [key, storedValue])
return [storedValue, setStoredValue]
}
In the above example, useLocalStorage
is a custom hook that manages the state of a value in local storage. It initializes the state using the useState
hook with a function that checks if the key exists in local storage. If the key exists, it returns the parsed item. If it doesn't, it returns the initialValue
. The useEffect
hook updates the local storage whenever the state changes.
Rules for Custom Hooks
The rules for custom hooks in React are the same as the rules for using standard hooks. The two main rules are:
- Only call hooks at the top level of your React functions.
- Only call hooks from React functions, not any regular JavaScript functions.
Here's an example of a custom hook that breaks these rules:
function useBreakingHook() {
if (someCondition) {
useState(false) // violates the "only call hooks at the top level" rule
}
function nestedFunction() {
useEffect(() => {}) // violates the "only call hooks from React functions" rule
}
}
In the above code, useState
is called inside an if
statement, violating the first rule. useEffect
is called from a nested function, violating the second rule. Following these rules ensures that the state and lifecycle of your hooks and components function as expected.
Building a componentDidMount Hook
In class-based components, the componentDidMount
lifecycle method runs once the component is added to the DOM. With hooks, you can simulate this behavior with the useEffect hook.
import { useEffect } from 'react'
function useComponentDidMount(callback) {
useEffect(() => {
callback()
}, [])
}
The useComponentDidMount
hook uses the useEffect
hook to simulate
the componentDidMount
lifecycle method. The empty array as the second argument to useEffect
ensures that it only runs once after the initial render, matching the behavior of componentDidMount
.
Using Third-Party Custom Hooks
There are plenty of open-source libraries that offer pre-built custom hooks you can use in your project. This saves you the time of creating common functionalities yourself. One such library is react-use
, which provides a large collection of ready-to-use hooks.
Here's an example of using a third-party custom hook:
import { useLocalStorage } from 'react-use'
function Component() {
const [value, setValue] = useLocalStorage('myKey', 'defaultValue')
// your component logic...
}
In this example, the useLocalStorage
hook from the react-use
library is used in a component. This hook works similarly to the custom useLocalStorage
hook we created earlier. It manages state that is synchronized with local storage. This demonstrates how third-party custom hooks can provide reusable functionalities and reduce the amount of code you need to write.
Remember that whenever you're using hooks, whether they're built-in hooks, custom hooks, or third-party hooks, always follow the rules of hooks
. If you need to dive deeper into hooks, check the official React docs for useState
, useEffect
, and useRef
. Also, if you need to learn more about components, take a look at the React components
section.