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.



