ahooks, react-use, and react-hooks are libraries that provide collections of reusable custom React hooks to simplify common frontend patterns like state management, side effects, DOM interactions, and performance optimizations. These packages aim to reduce boilerplate, promote best practices, and accelerate development by offering battle-tested utilities built on React’s hooks API. While all serve similar high-level goals, they differ significantly in design philosophy, API ergonomics, TypeScript support, testing rigor, and ecosystem alignment.
When scaling React applications, reinventing the wheel for common patterns—like managing async data, tracking element dimensions, or synchronizing state with localStorage—is both wasteful and risky. That’s where mature hook libraries come in. But not all are created equal. Let’s dissect ahooks, react-use, and the deprecated react-hooks through the lens of real-world engineering trade-offs.
ahooks emerges from Alibaba’s Ant Design ecosystem with an enterprise-first mindset. Every hook is backed by unit tests, detailed documentation, and explicit compatibility guarantees for React 18+ features like Strict Mode and concurrent rendering. The team treats breaking changes with surgical precision—often providing codemods during major upgrades.
react-use takes a more community-driven, utility-focused stance. It offers one of the widest catalogs of hooks (100+), often inspired by RxJS or Vue Composition API patterns. While well-maintained, its decentralized contribution model means some hooks receive less scrutiny than others—particularly around edge cases in modern React.
react-hooks, unfortunately, is a ghost town. Archived on GitHub with no commits since 2020, it predates React 18’s architectural shifts. Using it today risks hydration mismatches, memory leaks in Strict Mode, and security vulnerabilities from unmaintained dependencies.
TypeScript support isn’t just about annotations—it’s about developer velocity and runtime safety.
ahooks delivers first-class TypeScript with:
useRequest<TData, TError>)// ahooks: Type-safe async state
const { data, loading, error } = useRequest<Profile, ApiError>(
() => fetch('/api/profile').then(res => res.json())
);
// `data` is Profile | undefined, `error` is ApiError | undefined
react-use provides solid but occasionally loose typings. Many hooks use any internally or require manual type assertions:
// react-use: Requires type narrowing
const [value, setValue] = useLocalStorage('theme');
// value is string | null – you must handle null explicitly
react-hooks has no TypeScript definitions whatsoever. You’ll drown in @ts-ignore comments or write your own fragile typings.
Handling network requests correctly involves loading states, error boundaries, caching, and race condition handling. Here’s how they compare:
ahooks’s useRequest is a Swiss Army knife:
const {
data,
loading,
run: refetch,
mutate // Optimistic updates
} = useRequest(getUser, {
manual: true, // Don't auto-run
debounceWait: 500, // Built-in debouncing
onSuccess: (result) => {
message.success(`Loaded ${result.name}`);
}
});
// Handles cancellation tokens automatically
useEffect(() => {
refetch({ id: userId });
}, [userId]);
react-use favors composition over monolithic hooks. You’d chain simpler hooks:
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(false);
const fetchUser = useCallback(async (id: string) => {
setLoading(true);
try {
const res = await fetch(`/api/users/${id}`);
setUser(await res.json());
} finally {
setLoading(false);
}
}, []);
// No built-in cancellation – you’d need AbortController manually
This gives flexibility but shifts complexity to your codebase.
Need to track window size, element visibility, or clipboard events?
ahooks provides hooks like useSize and useInViewport with resize observer cleanup handled automatically:
const containerRef = useRef<HTMLDivElement>(null);
const size = useSize(containerRef); // Returns { width, height }
return <div ref={containerRef}>Width: {size?.width}</div>;
react-use offers similar utilities (useWindowSize, useMeasure) but with subtle differences:
const size = useMeasure(ref); // Requires manual ref assignment
// May trigger extra renders during initialization
Both avoid common pitfalls like memory leaks from forgotten event listeners—but ahooks tends to be more aggressive about defensive cleanup.
React 18’s double-invocation in Strict Mode exposes flawed hooks that don’t properly clean up effects. This is where maintenance rigor matters.
ahooks explicitly documents Strict Mode compatibility for every hook. For example, useInterval uses refs to track active intervals:
// ahooks' internal pattern
useEffect(() => {
const intervalId = setInterval(callback, delay);
return () => clearInterval(intervalId); // Guaranteed cleanup
}, [delay]);
react-use generally works but has known issues in edge cases (e.g., useAsyncFn may trigger duplicate requests during dev-mode double-renders without careful implementation).
react-hooks will leak timers, subscriptions, and network requests under Strict Mode—making it fundamentally incompatible with modern React.
| Scenario | Recommendation | Why |
|---|---|---|
| Enterprise app with Ant Design | ahooks | Seamless integration, audit-ready reliability |
| Rapid prototyping / indie project | react-use | Huge catalog, low barrier to entry |
| Legacy code migration | Neither | Replace react-hooks immediately with ahooks |
| Complex async workflows | ahooks | Built-in cancellation, retry logic, and cache management |
| Browser API experimentation | react-use | More niche hooks (e.g., useSpeechRecognition, useBattery) |
react-hooks. Its deprecation isn’t theoretical—it’s a technical liability.ahooks for mission-critical applications where correctness, test coverage, and long-term maintainability outweigh catalog breadth.react-use for exploratory work or when you need a specific utility not covered elsewhere—but audit its implementation for Strict Mode safety before production use.Remember: A hook library isn’t just about saving lines of code. It’s about inheriting someone else’s decisions around error handling, memory management, and React version compatibility. Choose wisely—their trade-offs become your technical debt.
Choose ahooks if you're building enterprise-grade React applications—especially with Ant Design—and need rigorously tested, production-ready hooks with strong TypeScript support and comprehensive documentation. It excels in scenarios requiring robust async state management (e.g., useRequest), debounced inputs, or DOM measurements, and its team actively maintains strict compatibility with React’s concurrent rendering model.
Do not use react-hooks in new projects. This package is deprecated and has been archived by its maintainers. It lacks updates for modern React features (e.g., Strict Mode compatibility), contains outdated patterns, and offers no TypeScript definitions. Migrate existing usage to ahooks or react-use immediately.
Choose react-use if you prioritize a broad catalog of lightweight, composable hooks with intuitive APIs for browser APIs (e.g., useLocalStorage, useMedia), animations, or reactive programming patterns. Its functional, utility-first approach suits rapid prototyping or apps needing granular control over side effects, though some hooks may require manual adaptation for concurrent rendering edge cases.
$ npm install --save ahooks
# or
$ yarn add ahooks
# or
$ pnpm add ahooks
# or
$ bun add ahooks
import { useRequest } from "ahooks";
$ git clone git@github.com:alibaba/hooks.git
$ cd hooks
$ pnpm run init
$ pnpm start
Open your browser and visit http://127.0.0.1:8000
We welcome all contributions, please read our CONTRIBUTING.MD first, let's build a better hooks library together.
Thanks to all the contributors: