How to Build a Custom Hook in React

Creating custom hooks allows you to extract and reuse stateful logic between React components. As the creator of CoreUI with over 11 years of React development experience, I build custom hooks extensively to share common functionality across UI components. Custom hooks are JavaScript functions that start with “use” and can call other hooks, making complex logic reusable and testable.

Create custom hooks by extracting stateful logic into functions that start with “use” and return the values you need.

import { useState, useEffect } from 'react'

// Custom hook for managing localStorage
function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key)
      return item ? JSON.parse(item) : initialValue
    } catch (error) {
      console.error('Error reading localStorage:', error)
      return initialValue
    }
  })

  const setValue = (value) => {
    try {
      setStoredValue(value)
      window.localStorage.setItem(key, JSON.stringify(value))
    } catch (error) {
      console.error('Error setting localStorage:', error)
    }
  }

  return [storedValue, setValue]
}

// Using the custom hook
function UserPreferences() {
  const [theme, setTheme] = useLocalStorage('theme', 'light')
  const [language, setLanguage] = useLocalStorage('language', 'en')

  return (
    <div>
      <select value={theme} onChange={(e) => setTheme(e.target.value)}>
        <option value="light">Light</option>
        <option value="dark">Dark</option>
      </select>
      <select value={language} onChange={(e) => setLanguage(e.target.value)}>
        <option value="en">English</option>
        <option value="es">Spanish</option>
      </select>
    </div>
  )
}

Custom hooks must start with “use” to follow React’s rules of hooks. They can use other hooks like useState, useEffect, and even other custom hooks. The hook should return an array or object containing the stateful values and functions that components need. This pattern promotes code reuse, separation of concerns, and makes complex logic easier to test in isolation.

Best Practice Note:

In CoreUI components, we create custom hooks for data fetching, form validation, theme management, and responsive design logic. This approach keeps our components clean and focused on rendering while making business logic reusable across the entire component library.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to get element ID in JavaScript
How to get element ID in JavaScript

Understanding and Resolving the “React Must Be in Scope When Using JSX
Understanding and Resolving the “React Must Be in Scope When Using JSX

How to limit items in a .map loop in JavaScript
How to limit items in a .map loop in JavaScript

How to Remove Elements from a JavaScript Array
How to Remove Elements from a JavaScript Array

Answers by CoreUI Core Team