npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@xumi/rhooks

v1.5.4

Published

A collection of useful React hooks built with TypeScript.

Readme

@xumi/rhooks

一个基于 TypeScript 构建的有用 React Hooks 集合。

English | 中文

安装

npm install @xumi/[email protected]
# 或
pnpm add @xumi/[email protected]
# 或
yarn add @xumi/[email protected]

可用的 Hooks

Hook 详情

useToggle

用于切换布尔值的 hook。

import { useToggle } from '@xumi/rhooks'

const [isOpen, toggle, open, close] = useToggle(false)

<button onClick={toggle}>切换</button>
<button onClick={open}>打开</button>
<button onClick={close}>关闭</button>

useBoolean

用于管理布尔值状态的 hook,返回包含多个方法的对象。

import { useBoolean } from '@xumi/rhooks'

const [isOpen, { toggle, setTrue, setFalse, set }] = useBoolean(false)

<button onClick={toggle}>切换</button>
<button onClick={setTrue}>打开</button>
<button onClick={setFalse}>关闭</button>
<button onClick={() => set(true)}>设置为 true</button>

useLocalStorageState

将状态存储在 localStorage 中的 hook,页面刷新后状态依然保持。

import { useLocalStorageState } from "@xumi/rhooks";

// 基本用法
const [count, setCount] = useLocalStorageState<number>("count", {
	defaultValue: 0,
});

// 使用自定义序列化和反序列化
const [user, setUser] = useLocalStorageState<User>("user", {
	defaultValue: { name: "John" },
	serializer: (value) => JSON.stringify(value),
	deserializer: (value) => JSON.parse(value),
});

// 使用函数作为默认值
const [data, setData] = useLocalStorageState<Data>("data", {
	defaultValue: () => fetchInitialData(),
});

useDebounceFn

防抖函数 Hook,用于防抖执行函数。

import { useDebounceFn } from "@xumi/rhooks";

const { run, cancel, flush } = useDebounceFn(
	(value: string) => {
		console.log(value);
	},
	{ wait: 500 }
);

// 调用 run 来触发防抖
run("hello");

// 取消待执行的防抖函数
cancel();

// 立即执行并返回结果
const result = flush();

配置选项

  • wait: 防抖等待时间(毫秒),默认 1000ms
  • leading: 是否在延迟开始前调用函数,默认 false
  • trailing: 是否在延迟结束后调用函数,默认 true
  • maxWait: 最大等待时间(毫秒),用于设置防抖函数的最大延迟时间

useThrottleFn

节流函数 Hook,用于节流执行函数。在固定时间间隔内最多执行一次。

import { useThrottleFn } from "@xumi/rhooks";

const { run, cancel, flush } = useThrottleFn(
	(value: string) => {
		console.log(value);
	},
	{ wait: 500 }
);

// 调用 run 来触发节流
run("hello");

// 取消待执行的节流函数
cancel();

// 立即执行并返回结果
const result = flush();

配置选项

  • wait: 节流等待时间(毫秒),默认 1000ms
  • leading: 是否在延迟开始前调用函数,默认 true
  • trailing: 是否在延迟结束后调用函数,默认 true

与 useDebounceFn 的区别

  • 防抖(Debounce):在事件停止触发后执行,适合搜索框输入、窗口 resize 等场景
  • 节流(Throttle):在固定时间间隔内最多执行一次,适合滚动事件、鼠标移动等场景

usePrevious

获取上一次的值。

import { usePrevious } from "@xumi/rhooks";

const [count, setCount] = useState(0);
const prevCount = usePrevious(count);

useWindowSize

获取窗口尺寸。

import { useWindowSize } from "@xumi/rhooks";

const { width, height } = useWindowSize();

return (
	<div>
		窗口尺寸: {width} x {height}
	</div>
);

useCounter

计数器 hook。

import { useCounter } from '@xumi/rhooks'

const [count, increment, decrement, reset, setCount] = useCounter(0)

<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>重置</button>

useTimeout

定时器 hook。

import { useTimeout } from "@xumi/rhooks";

const clear = useTimeout(() => {
	console.log("1 秒后执行");
}, 1000);

// 可以手动清除
clear();

useInterval

循环定时器 hook。

import { useInterval } from "@xumi/rhooks";
import { useState, useRef } from "react";

const [count, setCount] = useState(0);

// 基本用法
const { clear } = useInterval(() => {
	setCount(count + 1);
}, 1000);

// 立即执行的用法
const { clear: clear2 } = useInterval(
	() => {
		setCount(count + 1);
	},
	1000,
	{ immediate: true }
);

// 手动清除定时器
clear();

useMount

组件挂载时执行。

import { useMount } from "@xumi/rhooks";

useMount(() => {
	console.log("组件已挂载");
});

useUnmount

组件卸载时执行。

import { useUnmount } from "@xumi/rhooks";

useUnmount(() => {
	console.log("组件已卸载");
});

useUpdateEffect

只在依赖更新时执行的 effect,跳过首次渲染。

import { useUpdateEffect } from "@xumi/rhooks";

useUpdateEffect(() => {
	console.log("已更新:", count);
}, [count]);

useScroll

获取元素的滚动位置。

import { useScroll } from "@xumi/rhooks";
import React, { useRef } from "react";

function Demo() {
	const scrollRef = useRef(null);
	const scroll = useScroll(scrollRef);

	return (
		<div>
			<p>滚动位置: {JSON.stringify(scroll)}</p>
			<div
				style={{
					width: 300,
					height: 200,
					border: "1px solid #e8e8e8",
					overflow: "auto",
				}}
				ref={scrollRef}
			>
				<div style={{ height: 500, width: 500 }}>
					这是一个可滚动的区域,请尝试滚动查看效果
				</div>
			</div>
		</div>
	);
}

useHover

鼠标悬停状态 hook,用于检测元素是否被鼠标悬停。

import { useHover } from "@xumi/rhooks";

function Demo() {
	const [ref, isHovered] = useHover();

	return <div ref={ref}>{isHovered ? "鼠标悬停中" : "鼠标未悬停"}</div>;
}

useRequest

一个强大的异步数据管理 Hook,它将数据获取逻辑中的 loading 状态、data、error、请求、取消、刷新等所有环节都封装好了。

API

const { data, error, loading, run, cancel, refresh, reset } = useRequest(
	service,
	options
);
参数

| 参数 | 说明 | 类型 | 默认值 | | ------- | ---------------------- | -------------------------------- | ------ | | service | 请求函数,返回 Promise | (...args: any[]) => Promise<T> | - | | options | 配置项 | Options | - |

Options

| 参数 | 说明 | 类型 | 默认值 | | ------------- | ---------------------------------- | --------------------------------------- | ----------------- | | manual | 是否手动触发请求 | boolean | false | | defaultParams | 默认参数 | any[] | [] | | refreshDeps | 依赖数组,当依赖变化时自动重新请求 | any[] | [] | | cacheKey | 缓存的键值,设置后会启用缓存 | string | - | | cacheTime | 缓存时间,单位为毫秒 | number | 300000 (5 分钟) | | onSuccess | 请求成功时的回调 | (data: any, params: any[]) => void | - | | onError | 请求失败时的回调 | (error: Error, params: any[]) => void | - | | onFinally | 请求完成时的回调(无论成功或失败) | (params: any[]) => void | - |

返回值

| 参数 | 说明 | 类型 | | ------- | -------------- | ---------------------------- | | data | 请求返回的数据 | T \| undefined | | error | 请求错误信息 | Error \| undefined | | loading | 请求加载状态 | boolean | | run | 执行请求函数 | (...params: any[]) => void | | cancel | 取消请求函数 | () => void | | refresh | 刷新请求函数 | () => void | | reset | 重置状态函数 | () => void |

使用示例

import { useRequest } from "@xumi/rhooks";

// 基本用法
const { data, error, loading, run } = useRequest(async () => {
	const response = await fetch("/api/users");
	return response.json();
});

// 带参数的请求
const { data, error, loading, run } = useRequest(
	(userId) => fetch(`/api/users/${userId}`).then((res) => res.json()),
	{
		manual: true, // 手动触发
	}
);

// 使用缓存
const { data, loading } = useRequest(
	() => fetch("/api/user-info").then((res) => res.json()),
	{
		cacheKey: "user-info",
		cacheTime: 600000, // 10分钟
	}
);

// 依赖刷新
const userId = 1;
const { data, refresh } = useRequest(
	(id) => fetch(`/api/users/${id}`).then((res) => res.json()),
	{
		defaultParams: [userId],
		refreshDeps: [userId],
	}
);

useClickAway

点击外部区域检测,支持单个或多个目标元素。

import { useClickAway } from "@xumi/rhooks";

// 单个目标元素
const ref = useRef<HTMLDivElement>(null);
useClickAway(() => {
	setIsOpen(false);
}, ref);

// 多个目标元素
const ref1 = useRef<HTMLDivElement>(null);
const ref2 = useRef<HTMLButtonElement>(null);
useClickAway(() => {
	setIsOpen(false);
}, [ref1, ref2]);

return (
	<div>
		<button ref={ref2}>按钮</button>
		<div ref={ref1}>内容区域</div>
	</div>
);

License

MIT