@usefy/use-counter
v0.0.38
Published
A React hook for counter state management
Downloads
3,677
Readme
Overview
@usefy/use-counter is a simple yet powerful React hook for managing counter state. It provides a clean, intuitive API with stable function references, making it ideal for building increment/decrement UIs, pagination controls, quantity selectors, and more.
Part of the @usefy ecosystem — a collection of production-ready React hooks designed for modern applications.
Why use-counter?
- Zero Dependencies — Pure React implementation with no external dependencies
- TypeScript First — Full type safety with comprehensive type definitions
- Stable References — Functions are memoized with
useCallbackfor optimal performance - SSR Compatible — Works seamlessly with Next.js, Remix, and other SSR frameworks
- Lightweight — Minimal bundle footprint (~200B minified + gzipped)
- Well Tested — Comprehensive test coverage with Vitest
Installation
# npm
npm install @usefy/use-counter
# yarn
yarn add @usefy/use-counter
# pnpm
pnpm add @usefy/use-counterPeer Dependencies
This package requires React 18 or 19:
{
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0"
}
}Quick Start
import { useCounter } from "@usefy/use-counter";
function Counter() {
const { count, increment, decrement, reset } = useCounter(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}API Reference
useCounter(initialValue?)
A hook that manages counter state with increment, decrement, and reset capabilities.
Parameters
| Parameter | Type | Default | Description |
| -------------- | -------- | ------- | -------------------------------- |
| initialValue | number | 0 | The initial value of the counter |
Returns
| Property | Type | Description |
| ----------- | ------------ | --------------------------------------- |
| count | number | The current counter value |
| increment | () => void | Increases the counter by 1 |
| decrement | () => void | Decreases the counter by 1 |
| reset | () => void | Resets the counter to the initial value |
Examples
Basic Counter
import { useCounter } from "@usefy/use-counter";
function BasicCounter() {
const { count, increment, decrement, reset } = useCounter();
return (
<div className="counter">
<span className="count">{count}</span>
<div className="controls">
<button onClick={decrement} aria-label="Decrease">
−
</button>
<button onClick={increment} aria-label="Increase">
+
</button>
<button onClick={reset} aria-label="Reset">
Reset
</button>
</div>
</div>
);
}Starting with a Custom Value
import { useCounter } from "@usefy/use-counter";
function QuantitySelector() {
const { count, increment, decrement } = useCounter(1);
return (
<div className="quantity-selector">
<button
onClick={decrement}
disabled={count <= 1}
aria-label="Decrease quantity"
>
−
</button>
<span aria-label="Quantity">{count}</span>
<button onClick={increment} aria-label="Increase quantity">
+
</button>
</div>
);
}Pagination Control
import { useCounter } from "@usefy/use-counter";
function Pagination({ totalPages }: { totalPages: number }) {
const {
count: currentPage,
increment: nextPage,
decrement: prevPage,
reset,
} = useCounter(1);
return (
<nav className="pagination" aria-label="Pagination">
<button onClick={prevPage} disabled={currentPage <= 1}>
Previous
</button>
<span>
Page {currentPage} of {totalPages}
</span>
<button onClick={nextPage} disabled={currentPage >= totalPages}>
Next
</button>
<button onClick={reset}>First Page</button>
</nav>
);
}Multiple Independent Counters
import { useCounter } from "@usefy/use-counter";
function ScoreBoard() {
const teamA = useCounter(0);
const teamB = useCounter(0);
const resetAll = () => {
teamA.reset();
teamB.reset();
};
return (
<div className="scoreboard">
<div className="team">
<h3>Team A</h3>
<span className="score">{teamA.count}</span>
<button onClick={teamA.increment}>+1</button>
</div>
<div className="team">
<h3>Team B</h3>
<span className="score">{teamB.count}</span>
<button onClick={teamB.increment}>+1</button>
</div>
<button onClick={resetAll}>Reset Game</button>
</div>
);
}With Negative Values
import { useCounter } from "@usefy/use-counter";
function TemperatureAdjuster() {
const { count: temperature, increment, decrement, reset } = useCounter(-10);
return (
<div className="temperature">
<span>{temperature}°C</span>
<button onClick={increment}>Warmer</button>
<button onClick={decrement}>Cooler</button>
<button onClick={reset}>Reset to -10°C</button>
</div>
);
}TypeScript
This hook is written in TypeScript and provides full type inference out of the box.
import { useCounter } from "@usefy/use-counter";
// Return type is automatically inferred
const { count, increment, decrement, reset } = useCounter(0);
// count: number
// increment: () => void
// decrement: () => void
// reset: () => voidPerformance
The hook uses useCallback to memoize all returned functions, ensuring stable references across re-renders. This is particularly important when passing these functions as props to child components or using them as dependencies in other hooks.
const { increment, decrement, reset } = useCounter(0);
// These references remain stable across renders
useEffect(() => {
// Safe to use as dependencies
}, [increment, decrement, reset]);Testing
This package maintains comprehensive test coverage to ensure reliability and stability.
Test Coverage
📊 View Detailed Coverage Report (GitHub Pages)
Test Categories
- Default value initialization (0)
- Custom initial value
- Negative initial value
- Large number support
- Explicit zero initialization
- Increment from zero
- Increment from positive values
- Increment from negative values
- Multiple consecutive increments
- Decrement from positive values
- Decrement crossing zero boundary
- Decrement from negative values
- Multiple consecutive decrements
- Reset after increment operations
- Reset after decrement operations
- Reset to negative initial value
- Reset to zero
- Multiple reset operations
- Sequential mixed operations
- Zero boundary crossing
- State stability verification
- Alternating increment/decrement
- Large number operations
- Multiple independent hook instances
- Function reference stability across renders
Testing Stack
- Vitest — Fast, modern test runner
- @testing-library/react — React testing utilities
- jsdom — DOM environment for Node.js
License
MIT © mirunamu
This package is part of the usefy monorepo.
