hooks-belt
v1.0.11
Published
A comprehensive collection of useful React hooks for common use cases
Maintainers
Readme
Hooks Belt 🎯
A comprehensive collection of useful React hooks for common use cases. Built with TypeScript and designed for production use.
✨ Features
- 11 Custom Hooks - Covering the most common React development needs
- Full TypeScript Support - Complete type definitions and IntelliSense
- Production Ready - Well-tested and optimized for real-world usage
- Zero Dependencies - Only requires React as a peer dependency
- Tree Shakeable - Import only the hooks you need
📦 Installation
npm install hooks-beltor
yarn add hooks-belt🚀 Quick Start
import { useDebounce, useLocalStorage, useToggle, useDownloadFile } from 'hooks-belt'
function MyComponent() {
const [searchTerm, setSearchTerm] = useState('')
const debouncedSearchTerm = useDebounce(searchTerm, 300)
const [user, setUser] = useLocalStorage('user', { name: 'John' })
const [isOpen, toggle] = useToggle(false)
const { downloadFile, isLoading } = useDownloadFile()
// Your component logic here
}📚 Available Hooks
useDebounce
Delays the execution of a function or value update. Perfect for search inputs and API calls.
const [searchTerm, setSearchTerm] = useState('')
const debouncedSearchTerm = useDebounce(searchTerm, 500)
useEffect(() => {
// This will only run after the user stops typing for 500ms
searchAPI(debouncedSearchTerm)
}, [debouncedSearchTerm])useThrottle
Limits the rate at which a function can be executed. Great for scroll handlers and resize events.
const throttledScrollHandler = useThrottle(() => {
console.log('Scroll event throttled')
}, 100)
useEffect(() => {
window.addEventListener('scroll', throttledScrollHandler)
return () => window.removeEventListener('scroll', throttledScrollHandler)
}, [throttledScrollHandler])useLocalStorage
Provides a way to persist state in localStorage with automatic JSON serialization.
const [user, setUser] = useLocalStorage('user', { name: 'John', age: 30 })
// Update the user
setUser({ name: 'Jane', age: 25 })
// The value is automatically saved to localStorageuseMediaQuery
Responds to media queries and automatically updates when the query matches or doesn't match.
const isMobile = useMediaQuery('(max-width: 768px)')
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)')
return (
<div className={isMobile ? 'mobile-layout' : 'desktop-layout'}>
{isDarkMode ? 'Dark mode' : 'Light mode'}
</div>
)usePrevious
Returns the previous value of a state or prop. Useful for comparing current and previous values.
const [count, setCount] = useState(0)
const previousCount = usePrevious(count)
useEffect(() => {
if (previousCount !== undefined && count > previousCount) {
console.log('Count increased!')
}
}, [count, previousCount])useToggle
Provides a boolean state with toggle functionality and additional setter functions.
const [isOpen, toggle, setOpen, setClosed] = useToggle(false)
return (
<div>
<button onClick={toggle}>Toggle</button>
<button onClick={setOpen}>Open</button>
<button onClick={setClosed}>Close</button>
{isOpen && <Modal />}
</div>
)useOnClickOutside
Detects clicks outside of a specified element. Perfect for modals and dropdowns.
const modalRef = useRef<HTMLDivElement>(null)
const [isOpen, setIsOpen] = useState(false)
useOnClickOutside(modalRef, () => setIsOpen(false))
return (
{isOpen && (
<div ref={modalRef} className="modal">
Modal content
</div>
)}
)useFetch
Provides a way to fetch data with loading and error states.
const { data, loading, error, refetch } = useFetch('/api/users')
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<div>
{data?.map(user => <User key={user.id} user={user} />)}
<button onClick={refetch}>Refresh</button>
</div>
)useWindowSize
Tracks the window dimensions and automatically updates when the window is resized.
const { width, height } = useWindowSize()
return (
<div>
Window size: {width} x {height}
{width < 768 && <MobileMenu />}
</div>
)useInterval
Provides a way to run a function at regular intervals with pause/resume functionality.
const [count, setCount] = useState(0)
const [isRunning, setIsRunning] = useState(true)
useInterval(
() => setCount(c => c + 1),
isRunning ? 1000 : null
)
return (
<div>
Count: {count}
<button onClick={() => setIsRunning(!isRunning)}>
{isRunning ? 'Pause' : 'Resume'}
</button>
</div>
)useDownloadFile
Provides file download functionality with loading state management and automatic cleanup.
const { downloadFile, isLoading } = useDownloadFile()
const handleDownload = async () => {
const response = await fetch('/api/file')
const blob = await response.blob()
await downloadFile({
data: blob,
fileName: 'document.pdf'
})
}
return (
<button onClick={handleDownload} disabled={isLoading}>
{isLoading ? 'Downloading...' : 'Download File'}
</button>
)🧪 Testing
Run the test suite:
npm testRun tests in watch mode:
npm run test:watchGenerate coverage report:
npm run test:coverage🏗️ Development
Prerequisites
- Node.js 18+
- npm or yarn
Setup
- Clone the repository:
git clone https://github.com/morozander/hooks-belt.git
cd hooks-belt- Install dependencies:
npm install- Start development server:
npm run dev- Build the library:
npm run build:libProject Structure
hooks-belt/
├── src/
│ ├── hooks/ # Individual hook implementations
│ ├── test/ # Test setup and utilities
│ ├── App.tsx # Demo application
│ └── index.ts # Main export file
├── dist/ # Built library files
├── tests/ # Unit tests for each hook
├── package.json # Package configuration
├── tsconfig.json # TypeScript configuration
├── vitest.config.ts # Test configuration
└── README.md # This file🤝 Contributing
We welcome contributions! Here's how you can help:
Reporting Issues
- Use the GitHub issue tracker
- Include a clear description of the problem
- Provide steps to reproduce the issue
- Include your environment details
Submitting Pull Requests
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Add tests for new functionality
- Ensure all tests pass:
npm test - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
Code Style
- Follow the existing TypeScript/React patterns
- Include JSDoc comments for all public APIs
- Write comprehensive tests for new hooks
- Ensure your code passes linting:
npm run lint
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- Inspired by the React community's need for reusable hooks
- Built with modern tooling (Vite, TypeScript, Vitest)
- Thanks to all contributors and users
Made with ❤️ for the React community
