118 | // 下面的代码保持不变
119 | //...
120 | )}
121 |
122 | ```
123 |
--------------------------------------------------------------------------------
/docs/guide/tab.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 10
3 | title: 页面 Tab
4 | group: 特性
5 | ---
6 |
7 | # 页面 Tab
8 |
9 | 功能 参考 dumi 的 [页面 Tab](https://d.umijs.org/guide/page-tab)。
10 |
11 | 本主题包基于 antd 的 Tabs 做了一些样式优化,以获得更好的交互体验与视觉体验
12 |
--------------------------------------------------------------------------------
/docs/guide/theme.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 2
3 | title: Theme 主题
4 | group: 进阶特性
5 | toc: false
6 | token:
7 | contentMaxWidth: 1440
8 | sidebarWidth: 200
9 | ---
10 |
11 | # 主题
12 |
13 | `dumi-theme-antd-style` 默认同时支持亮色主题与暗色主题。
14 |
15 | ## 色板
16 |
17 | 主题色板基于 OKLCH 色彩模型构建。可以基于主色自定义出一套完整的设计系统色板。
18 |
19 |
20 |
--------------------------------------------------------------------------------
/docs/guide/toc.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 10
3 | title: 目录 Toc
4 | group: 特性
5 | toc: false
6 | ---
7 |
8 | # 目录
9 |
10 | 本主题的目录组件对移动端与桌面端适配良好,用户可以在不同设备上使用该组件来快速浏览页面内容
11 |
12 | 该组件支持通过配置 `toc: false` 来关闭目录,方便用户根据自己的需求进行选择。
13 |
14 | ```markdown
15 | ---
16 | toc: false
17 | ---
18 | ```
19 |
20 | 在主题自定义时,用户可以使用主题包提供的 Toc 组件,实现更加个性化的目录样式。具体使用方式可以参考主题包的文档说明。
21 |
22 | 更多关于目录组件的信息,可以查看[Toc 目录组件](/components/toc)的详细文档。
23 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '@dext7r/hooks'
3 | description: 一个基于 React 的自定义 Hooks 库,旨在提供一套方便、易用的针对不同场景的 Hooks 封装。该库涵盖了多种常见的前端请求操作,包括 Axios、Puppeteer、Fetch、Request 等,以帮助开发者更高效地处理网络请求和浏览器操作
4 | keywords: [Axios、Puppeteer、Fetch、Request, React, Hooks, 状态管理, Store]
5 | hero:
6 | title: '@dext7r/hooks'
7 | description: 一个基于React的自定义Hooks库
8 | actions:
9 | - text: 开始
10 | link: /guide
11 | - text: hooks
12 | link: /components
13 | features:
14 | - title: '江城子·乙卯正月二十日夜记梦'
15 | image: https://sns-img-hw.xhscdn.com/a99927df-beb7-3e43-9722-a79359af26cc?imageView2/2/w/1920/format/webp|imageMogr2/strip
16 | description:
- 十年生死两茫茫,不思量,自难忘。
- 千里孤坟,无处话凄凉。纵使相逢应不识,尘满面,鬓如霜。
- 夜来幽梦忽还乡,小轩窗,正梳妆。
- 相顾无言,惟有泪千行。料得年年肠断处,明月夜,短松冈。
17 | link: 'https://so.gushiwen.cn/mingju/juv_7c9202538459.aspx'
18 | imageType: primary
19 | row: 8
20 | - title: '菊花台'
21 | image: https://pic.rmb.bdstatic.com/bjh/events/064b9b18a4e4b9f6eab2dc6a4bfb8f9c.jpeg
22 | description:
- 我一身的戎装呼啸沧桑
- 天微微亮你轻声的叹
- 一夜惆怅如此委婉
- 菊花残满地伤
23 | link: 'http://www.kuwo.cn/play_detail/3327329?from=baidu'
24 | imageType: primary
25 | row: 8
26 | - title: '子衿'
27 | image: https://sns-img-hw.xhscdn.com/96ddbb57-621b-326f-8b3d-39ff05dbd836?imageView2/2/w/1920/format/webp|imageMogr2/strip
28 | description:
- 青青子衿,悠悠我心。纵我不往,子宁不嗣音?
- 青青子佩,悠悠我思。纵我不往,子宁不来?
29 | link: 'https://hanyu.baidu.com/shici/detail?from=kg1&highlight=%E9%9D%92%E9%9D%92%E5%AD%90%E8%A1%BF%EF%BC%8C%E6%82%A0%E6%82%A0%E6%88%91%E5%BF%83%E3%80%82&pid=48ff058caec5470b898052338d6f94de&srcid=51369'
30 | imageType: primary
31 | row: 8
32 | ---
33 |
34 |
35 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/eslint.config.js
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@dext7r/hooks",
3 | "version": "0.3.0",
4 | "description": "@dext7r/hooks is a custom Hooks library for React, designed to provide a convenient and easy-to-use set of Hooks tailored for various scenarios. This library encompasses a range of common frontend request operations, including Axios, Puppeteer, Fetch, Request, and more, to facilitate efficient handling of network requests and browser interactions。@dext7r/hooks 是一个基于 React 的自定义 Hooks 库,旨在提供一套方便、易用的针对不同场景的 Hooks 封装。该库涵盖了多种常见的前端请求操作,包括 Axios、Puppeteer、Fetch、Request 等,以帮助开发者更高效地处理网络请求和浏览器操作",
5 | "keywords": [
6 | "@dext7r/hooks",
7 | "@dext7r",
8 | "hooks",
9 | "react",
10 | "react-hooks",
11 | "react-library",
12 | "react-component",
13 | "react-components",
14 | "react-component-library"
15 | ],
16 | "homepage": "https://hooks.h7ml.cn",
17 | "bugs": {
18 | "url": "https://github.com/h7ml/hooks/issues/new"
19 | },
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/h7ml/hooks.git"
23 | },
24 | "license": "Apache-2.0",
25 | "author": {
26 | "name": "h7ml",
27 | "github": "https://github.com/h7ml",
28 | "mail": "h7ml@qq.com"
29 | },
30 | "sideEffects": false,
31 | "main": "lib/index.js",
32 | "jsdelivr": "lib/index.js",
33 | "unpkg": "lib/index.js",
34 | "module": "es/index.js",
35 | "types": "lib/index.d.ts",
36 | "files": [
37 | "lib",
38 | "es"
39 | ],
40 | "scripts": {
41 | "build": "father build",
42 | "build:watch": "father dev",
43 | "changelog": "conventional-changelog -n node_modules/conventional-changelog-gitmoji-config -i CHANGELOG.md -s -r 0",
44 | "ci": "npm run lint && npm run type-check && npm run doctor && npm run build",
45 | "clean": "rm -rf es lib dist coverage .dumi/tmp .eslintcache",
46 | "commit": "git-cz",
47 | "dev": "dumi dev",
48 | "docs:build": "dumi build",
49 | "doctor": "father doctor",
50 | "lint": "eslint .",
51 | "prepare": "husky install && npm run setup",
52 | "prepublishOnly": "npm run doctor && npm run build",
53 | "prettier": "prettier -c --write \"**/**\"",
54 | "release": "semantic-release",
55 | "semantic-release": "dotenv -c -- semantic-release",
56 | "semantic-release:local": "dotenv -c -- semantic-release --no-ci",
57 | "setup": "dumi setup",
58 | "start": "dumi dev",
59 | "test": "vitest --passWithNoTests",
60 | "test:coverage": "vitest run --coverage --passWithNoTests",
61 | "test:update": "vitest -u",
62 | "type-check": "tsc -p tsconfig-check.json",
63 | "updates": "ncu -u && pnpm install"
64 | },
65 | "commitlint": {
66 | "extends": [
67 | "@commitlint/config-conventional"
68 | ]
69 | },
70 | "lint-staged": {
71 | "*.{js,jsx}": [
72 | "eslint --fix",
73 | "prettier --write"
74 | ],
75 | "*.{md,json}": [
76 | "prettier --write --no-error-on-unmatched-pattern"
77 | ],
78 | "*.{ts,tsx}": [
79 | "eslint --fix",
80 | "prettier --parser=typescript --write"
81 | ]
82 | },
83 | "config": {
84 | "commitizen": {
85 | "path": "node_modules/cz-git"
86 | }
87 | },
88 | "dependencies": {
89 | "@ant-design/icons": "^5.3.6",
90 | "antd": "^5.16.1",
91 | "antd-style": "^3.6.2",
92 | "babel-plugin-import": "^1.13.8",
93 | "copy-to-clipboard": "^3.3.3",
94 | "lodash": "^4.17.21",
95 | "react-layout-kit": "^1.9.0",
96 | "streamsaver": "^2.0.6"
97 | },
98 | "devDependencies": {
99 | "@commitlint/cli": "^19.2.1",
100 | "@commitlint/config-conventional": "^19.1.0",
101 | "@testing-library/react": "^16",
102 | "@types/react": "^18.2.77",
103 | "@types/react-dom": "^18.2.25",
104 | "@types/streamsaver": "^2.0.4",
105 | "@umijs/lint": "^4.1.9",
106 | "@vitest/coverage-v8": "latest",
107 | "commitizen": "^4.3.0",
108 | "commitlint": "^19",
109 | "commitlint-config-gitmoji": "^2",
110 | "concurrently": "^8",
111 | "conventional-changelog-gitmoji-config": "^1",
112 | "cross-env": "^7",
113 | "cz-git": "^1.9.1",
114 | "dotenv-cli": "^7.4.1",
115 | "dumi": "^2.2.17",
116 | "dumi-theme-antd-style": "^0.31.0",
117 | "eslint": "^9.0.0",
118 | "father": "^4.4.0",
119 | "husky": "^9.0.11",
120 | "jsdom": "^24",
121 | "lint-staged": "^15.2.2",
122 | "npm-check-updates": "^16.14.18",
123 | "prettier": "^3.2.5",
124 | "prettier-plugin-organize-imports": "^4.0.0",
125 | "prettier-plugin-packagejson": "^2.5.0",
126 | "react": "^18.2.0",
127 | "react-dom": "^18.2.0",
128 | "semantic-release": "^24",
129 | "semantic-release-config-gitmoji": "^1",
130 | "stylelint": "^16.3.1",
131 | "typescript": "^5.4.5",
132 | "vitest": "latest"
133 | },
134 | "peerDependencies": {
135 | "react": ">=16.9.0",
136 | "react-dom": ">=16.9.0"
137 | },
138 | "packageManager": "pnpm@7.26.3",
139 | "volta": {
140 | "node": "18.0.0"
141 | },
142 | "publishConfig": {
143 | "access": "public",
144 | "registry": "https://registry.npmjs.org",
145 | "tag": "latest"
146 | },
147 | "licenses": [
148 | {
149 | "type": "Apache-2.0",
150 | "url": "https://github.com/h7ml/hooks/tree/main/LICENSE"
151 | }
152 | ]
153 | }
154 |
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/public/logo.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | Disallow:https://hooks.h7ml.cn/sitemap.xml
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["config:base"]
3 | }
4 |
--------------------------------------------------------------------------------
/src/hooks/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 简介
3 | nav:
4 | title: hooks
5 | order: 1
6 | apiHeader: false
7 | group:
8 | title: 介绍
9 | order: -1
10 | ---
11 |
12 | # 这是什么?
13 |
14 | `@dext7r/hooks` 是一个基于 `React` 的自定义 `Hooks` 库,旨在提供一套方便、易用的针对不同场景的 `Hooks` 封装。该库涵盖了多种常见的前端请求操作,包括 `Axios`、`Puppeteer`、`Fetch`、`Request` 等,以帮助开发者更高效地处理网络请求和浏览器操作
15 |
16 | ## 问题反馈
17 |
18 | 如果在使用过程中发现任何问题、或者有改善建议,欢迎在 [**GitHub Issues**](https://github.com/h7ml/hooks/issues) 进行反馈
19 |
--------------------------------------------------------------------------------
/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { default as useBattery } from './useBattery';
2 | export { default as useControlled } from './useControlled';
3 | export { default as useCookie } from './useCookie';
4 | export { default as useCopy, type useCopyProps } from './useCopy';
5 | export { default as useCountDown } from './useCountDown';
6 | export { default as useCounter } from './useCounter';
7 | export { default as useCycleList } from './useCycleList';
8 | export { default as useDebounce } from './useDebounce';
9 | export { default as useEvent } from './useEvent';
10 | export { default as useFileDownloader } from './useFileDownloader';
11 | export { default as useFirstMountState } from './useFirstMountState';
12 | export { default as useGeolocation } from './useGeolocation';
13 | export { default as useHover } from './useHover';
14 | export { default as useHoverDirty } from './useHoverDirty';
15 | export { default as useIdle } from './useIdle';
16 | export { default as useInterval } from './useInterval';
17 | export { default as useLatest } from './useLatest';
18 | export { default as useLocalStorage } from './useLocalStorage';
19 | export { default as useLocation } from './useLocation';
20 | export { default as useMeasure } from './useMeasure';
21 | export { default as useMedia } from './useMedia';
22 | export { default as useMediaDevices } from './useMediaDevices';
23 | export { default as useMount } from './useMount';
24 | export { default as useMountedState } from './useMountedState';
25 | export { default as useNetwork } from './useNetwork';
26 | export { default as usePrevious } from './usePrevious';
27 | export { default as useRafState } from './useRafState';
28 | export { default as useSafeState } from './useSafeState';
29 | export { default as useSessionStorage } from './useSessionStorage';
30 | export { default as useThrottle } from './useThrottle';
31 | export { default as useToggle } from './useToggle';
32 | export { default as useUnmount } from './useUnmount';
33 | export { default as useUnmountedRef } from './useUnmountedRef';
34 | export { default as useVirtualList } from './useVirtualList';
35 |
--------------------------------------------------------------------------------
/src/hooks/useBattery/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useBattery } from '@dext7r/hooks';
2 | import { useEffect, useState } from 'react';
3 |
4 | export default () => {
5 | const battery = useBattery();
6 | const [batteryLevel, setBatteryLevel] = useState
(null);
7 |
8 | useEffect(() => {
9 | if (battery) {
10 | setBatteryLevel(battery.level * 100);
11 | }
12 | }, [battery]);
13 |
14 | return (
15 | <>
16 | Battery Status
17 | {batteryLevel !== null ? (
18 | Battery Level: {batteryLevel.toFixed(2)}%
19 | ) : (
20 | Loading battery status...
21 | )}
22 | >
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/hooks/useBattery/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: device
4 | title: useBattery
5 | description: The useBattery hook is a custom React hook that provides access to the battery status and charging information using the Battery API available in modern browsers. It returns the BatteryManager object that can be used to check the battery level, charging status, and other battery-related information.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useBattery/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | interface CustomBatteryManager {
4 | level: number;
5 | charging: boolean;
6 | chargingTime: number;
7 | dischargingTime: number;
8 | addEventListener(
9 | type: string,
10 | listener: EventListenerOrEventListenerObject,
11 | options?: boolean | AddEventListenerOptions,
12 | ): void;
13 | removeEventListener(
14 | type: string,
15 | listener: EventListenerOrEventListenerObject,
16 | options?: boolean | EventListenerOptions,
17 | ): void;
18 | }
19 |
20 | const useBattery = (): CustomBatteryManager | null => {
21 | const [battery, setBattery] = useState(null);
22 |
23 | useEffect(() => {
24 | const handleBatteryChange = (event: Event) => {
25 | const batteryManager = event.target as unknown as CustomBatteryManager;
26 | setBattery(batteryManager);
27 | };
28 |
29 | if ('getBattery' in navigator) {
30 | (navigator as any).getBattery().then((batteryManager: CustomBatteryManager) => {
31 | setBattery(batteryManager);
32 | batteryManager.addEventListener('levelchange', handleBatteryChange);
33 | batteryManager.addEventListener('chargingchange', handleBatteryChange);
34 | batteryManager.addEventListener('dischargingtimechange', handleBatteryChange);
35 | batteryManager.addEventListener('chargingtimechange', handleBatteryChange);
36 | });
37 | } else {
38 | console.warn('Battery API is not supported in this browser.');
39 | }
40 |
41 | return () => {
42 | if (battery) {
43 | battery.removeEventListener('levelchange', handleBatteryChange);
44 | battery.removeEventListener('chargingchange', handleBatteryChange);
45 | battery.removeEventListener('dischargingtimechange', handleBatteryChange);
46 | battery.removeEventListener('chargingtimechange', handleBatteryChange);
47 | }
48 | };
49 | }, []);
50 |
51 | return battery;
52 | };
53 |
54 | export default useBattery;
55 |
--------------------------------------------------------------------------------
/src/hooks/useControlled/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useControlled } from '@dext7r/hooks';
2 | import { useState } from 'react';
3 |
4 | export default () => {
5 | const [controlledValue, isControlled] = useControlled(
6 | undefined,
7 | 'default value',
8 | );
9 | const [inputValue, setInputValue] = useState('');
10 |
11 | const handleChange = (e: React.ChangeEvent) => {
12 | if (!isControlled) {
13 | setInputValue(e.target.value);
14 | }
15 | };
16 |
17 | return (
18 | <>
19 | useControlled Example
20 | {isControlled ? (
21 |
22 |
This component is controlled.
23 |
24 |
Controlled value: {controlledValue}
25 |
26 | ) : (
27 |
28 |
This component is not controlled.
29 |
30 |
Input value: {inputValue}
31 |
32 | )}
33 | >
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/src/hooks/useControlled/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: state
4 | title: useControlled
5 | description: The useControlled hook is a custom React hook that tracks whether a component is controlled or not. It helps to handle state management for controlled and uncontrolled components.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useControlled/index.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | const useControlled = (value: T | undefined, defaultValue: T): [T, boolean] => {
4 | const [controlledValue, setControlledValue] = useState(value);
5 | const isControlled = value !== undefined;
6 |
7 | useEffect(() => {
8 | if (isControlled) {
9 | setControlledValue(value);
10 | } else {
11 | setControlledValue(defaultValue);
12 | }
13 | }, [value, defaultValue, isControlled]);
14 |
15 | return [controlledValue as T, isControlled];
16 | };
17 |
18 | export default useControlled;
19 |
--------------------------------------------------------------------------------
/src/hooks/useCookie/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCookie } from '@dext7r/hooks';
2 | import { Button, Input, message } from 'antd';
3 | import { useState } from 'react';
4 |
5 | const AllCookies = () => {
6 | const [cookieName, setCookieName] = useState('');
7 | const [cookieValue, updateCookie, deleteCookie] = useCookie(cookieName);
8 |
9 | const handleUpdate = () => {
10 | if (cookieName && cookieValue !== undefined) {
11 | updateCookie(cookieValue, { maxAge: 3600 }); // Set cookie with maxAge of 1 hour
12 | message.success('Cookie updated successfully!');
13 | } else {
14 | message.error('Please enter a cookie name and value to update the cookie.');
15 | }
16 | };
17 |
18 | const handleDelete = () => {
19 | if (cookieName) {
20 | deleteCookie(); // Delete the cookie
21 | message.success('Cookie deleted successfully!');
22 | } else {
23 | message.error('Please enter a cookie name to delete the cookie.');
24 | }
25 | };
26 |
27 | return (
28 | <>
29 | setCookieName(e.target.value)}
33 | placeholder="Enter Cookie Name"
34 | />
35 | updateCookie(e.target.value, { maxAge: 3600 })}
39 | placeholder="Enter Cookie Value"
40 | />
41 |
44 |
45 | Current Cookie Value: {cookieValue ? cookieValue : 'N/A'}
46 | >
47 | );
48 | };
49 |
50 | export default AllCookies;
51 |
--------------------------------------------------------------------------------
/src/hooks/useCookie/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group:
4 | title: 'store'
5 | title: useCookie
6 | description: The useCookie hook is a custom React hook that facilitates the storage, updating, and deletion of values within the CookieStore. It provides an array containing the current value of the cookie, a function to update the cookie with a new value, and a function to delete the cookie. This hook is useful for managing cookies and storing data on the client-side for various purposes, such as user preferences or session management.
7 | ---
8 |
9 | ## Default
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/hooks/useCookie/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | const useCookie = (
4 | cookieName: string,
5 | ): [string | undefined, (value: string, options?: CookieOptions) => void, () => void] => {
6 | const getCookie = (name: string): string | undefined => {
7 | const value = `; ${document.cookie}`;
8 | const parts = value.split(`; ${name}=`);
9 | if (parts.length === 2) return parts.pop()?.split(';').shift();
10 | };
11 |
12 | const [cookieValue, setCookieValue] = useState(getCookie(cookieName));
13 |
14 | const updateCookie = useCallback(
15 | (value: string, options: CookieOptions = {}): void => {
16 | const { maxAge, expires, path, domain, secure } = options;
17 | let cookieString = `${cookieName}=${encodeURIComponent(value)}`;
18 | if (maxAge) cookieString += `; max-age=${maxAge}`;
19 | if (expires) cookieString += `; expires=${expires.toUTCString()}`;
20 | if (path) cookieString += `; path=${path}`;
21 | if (domain) cookieString += `; domain=${domain}`;
22 | if (secure) cookieString += `; secure`;
23 | document.cookie = cookieString;
24 | setCookieValue(value);
25 | },
26 | [cookieName],
27 | );
28 |
29 | const deleteCookie = useCallback((): void => {
30 | document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
31 | setCookieValue(undefined);
32 | }, [cookieName]);
33 |
34 | return [cookieValue, updateCookie, deleteCookie];
35 | };
36 |
37 | export default useCookie;
38 |
39 | interface CookieOptions {
40 | maxAge?: number;
41 | expires?: Date;
42 | path?: string;
43 | domain?: string;
44 | secure?: boolean;
45 | }
46 |
--------------------------------------------------------------------------------
/src/hooks/useCopy/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCopy } from '@dext7r/hooks';
2 | import { Button, Input, message } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [value, setValue] = useState();
7 |
8 | const onSuccess = (text: string) => {
9 | message.success(`成功复制: ${text}`);
10 | };
11 |
12 | const onError = (err: Error) => {
13 | message.error(`复制失败: ${err.message}`);
14 | };
15 |
16 | // Pass useCopyProps to the useCopy hook
17 | const [copyText, copy] = useCopy({ onSuccess, onError });
18 |
19 | return (
20 | <>
21 | 复制的再好。也复制不了曾经的记忆~
22 | setValue(v.target.value)}
26 | />
27 |
30 | {copyText ? `复制结果: ${copyText}` : ''}
31 | >
32 | );
33 | };
34 |
--------------------------------------------------------------------------------
/src/hooks/useCopy/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useCopy
5 | description: The useCopy hook is a custom React hook that simplifies the process of copying text to the clipboard in a React component. It utilizes the copy-to-clipboard library and provides a tuple with the current copied text and a copy function. The copy function attempts to copy a provided value to the clipboard and handles success and error callbacks. Overall, useCopy makes text copying in React components more convenient.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useCopy/index.tsx:
--------------------------------------------------------------------------------
1 | import writeText from 'copy-to-clipboard';
2 | import { useCallback } from 'react';
3 | import useSafeState from '../useSafeState';
4 |
5 | export type CopySuccessFn = (text: string) => void;
6 |
7 | export interface useCopyProps {
8 | onSuccess?: CopySuccessFn;
9 | onError?: (err: Error) => void;
10 | }
11 |
12 | const useCopy = (props?: useCopyProps): [string | undefined, (value?: string | number) => void] => {
13 | const [copyText, setCopyText] = useSafeState(undefined);
14 |
15 | const copy = useCallback(
16 | (value?: string | number) => {
17 | if (!value) return setCopyText(undefined);
18 | try {
19 | writeText(value.toString());
20 | setCopyText(value.toString());
21 | props?.onSuccess?.(value.toString()); // Call onSuccess if provided
22 | } catch (err) {
23 | setCopyText(undefined);
24 | props?.onError?.(err as Error); // Call onError if provided
25 | }
26 | },
27 | [props],
28 | );
29 |
30 | return [copyText, copy];
31 | };
32 |
33 | export default useCopy;
34 |
--------------------------------------------------------------------------------
/src/hooks/useCountDown/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCountDown } from '@dext7r/hooks';
2 | import { getHMSTime } from '..';
3 |
4 | const CountdownDemo = () => {
5 | const now = new Date();
6 | const tomorrow = new Date();
7 | tomorrow.setDate(now.getDate() + 1);
8 | tomorrow.setHours(0, 0, 0, 0);
9 | const diffInSec = Math.floor((tomorrow.getTime() - now.getTime()) / 1000);
10 |
11 | const [hour, minute, second] = useCountDown(
12 | diffInSec,
13 | getHMSTime,
14 | () => {
15 | console.log('Countdown reached zero!');
16 | },
17 | true,
18 | ); // 设置 autoStart 为 true,自动启动倒计时
19 |
20 | return {`${hour}:${minute}:${second}`}
;
21 | };
22 |
23 | export default CountdownDemo;
24 |
--------------------------------------------------------------------------------
/src/hooks/useCountDown/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: state
4 | title: useCountDown
5 | description: The useCountDown hook is a custom React hook that returns the remaining minutes for a countdown. It gracefully decrements the countdown minutes until it reaches zero. You can also provide a callback function to handle actions when the countdown reaches zero.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useCountDown/index.ts:
--------------------------------------------------------------------------------
1 | import { useInterval } from '@dext7r/hooks';
2 | import { useEffect, useState } from 'react';
3 |
4 | const padZero = (time: number): string => {
5 | return `${time}`.length < 2 ? `0${time}` : `${time}`;
6 | };
7 |
8 | export const getHMSTime = (timeDiff: number): [string, string, string] => {
9 | if (timeDiff <= 0) {
10 | return ['00', '00', '00'];
11 | }
12 | if (timeDiff > 100 * 3600) {
13 | return ['99', '59', '59'];
14 | }
15 | const hour = Math.floor(timeDiff / 3600);
16 | const minute = Math.floor((timeDiff - hour * 3600) / 60);
17 | const second = timeDiff - hour * 3600 - minute * 60;
18 | return [padZero(hour), padZero(minute), padZero(second)];
19 | };
20 |
21 | const useCountDown = (
22 | time: number,
23 | format: (num: number) => [string, string, string] = getHMSTime,
24 | callback?: () => void,
25 | autoStart: boolean = true,
26 | ) => {
27 | const [remainTime, setRemainTime] = useState(time);
28 | const [delay, setDelay] = useState(autoStart ? 1000 : null);
29 |
30 | useInterval(() => {
31 | if (remainTime <= 0) {
32 | setDelay(null);
33 | return;
34 | }
35 | setRemainTime(remainTime - 1);
36 | }, delay);
37 |
38 | useEffect(() => {
39 | if (time > 0 && remainTime <= 0) {
40 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions
41 | callback && callback();
42 | }
43 | }, [callback, remainTime, time]);
44 |
45 | const [hour, minute, second] = format(remainTime);
46 |
47 | return [hour, minute, second] as const;
48 | };
49 |
50 | export default useCountDown;
51 |
--------------------------------------------------------------------------------
/src/hooks/useCounter/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCounter } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 |
4 | export default () => {
5 | const { count, increment, decrement, reset } = useCounter(0);
6 |
7 | return (
8 | <>
9 | Count: {count}
10 |
11 |
12 |
13 | >
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/src/hooks/useCounter/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: state
4 | title: useCounter
5 | description: The useCounter hook is a custom React state hook that tracks a numeric value. It provides functions to increment, decrement, and reset the counter.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useCounter/index.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | const useCounter = (initialValue: number = 0) => {
4 | const [count, setCount] = useState(initialValue);
5 |
6 | const increment = (step: number = 1) => {
7 | setCount((prevCount) => prevCount + step);
8 | };
9 |
10 | const decrement = (step: number = 1) => {
11 | setCount((prevCount) => prevCount - step);
12 | };
13 |
14 | const reset = () => {
15 | setCount(initialValue);
16 | };
17 |
18 | return {
19 | count,
20 | increment,
21 | decrement,
22 | reset,
23 | };
24 | };
25 |
26 | export default useCounter;
27 |
--------------------------------------------------------------------------------
/src/hooks/useCycleList/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCycleList } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 |
4 | const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
5 |
6 | export default () => {
7 | const [currentItem, nextItem, prevItem] = useCycleList(items, true);
8 |
9 | return (
10 | <>
11 | useCycleList Example
12 | Current Item: {currentItem}
13 |
14 |
15 | >
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/src/hooks/useCycleList/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: state
4 | title: useCycleList
5 | description: The useCycleList hook is a custom React hook that allows you to cycle through a list of items. It maintains the state of the currently selected item and provides functions to navigate to the next or previous item in the list.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useCycleList/index.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | const useCycleList = (
4 | items: T[],
5 | loop: boolean = false,
6 | ): [T, () => void, () => void] => {
7 | const [currentIndex, setCurrentIndex] = useState(0);
8 |
9 | const nextItem = useCallback(() => {
10 | setCurrentIndex((prevIndex) =>
11 | loop ? (prevIndex + 1) % items.length : Math.min(prevIndex + 1, items.length - 1),
12 | );
13 | }, [items.length, loop]);
14 |
15 | const prevItem = useCallback(() => {
16 | setCurrentIndex((prevIndex) =>
17 | loop ? (prevIndex - 1 + items.length) % items.length : Math.max(prevIndex - 1, 0),
18 | );
19 | }, [items.length, loop]);
20 |
21 | const currentItem = items[currentIndex];
22 |
23 | return [currentItem, nextItem, prevItem];
24 | };
25 |
26 | export default useCycleList;
27 |
--------------------------------------------------------------------------------
/src/hooks/useDebounce/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useDebounce } from '@dext7r/hooks';
2 | import { Input } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [inputValue, setInputValue] = useState('');
7 | const debouncedValue = useDebounce(inputValue, 500);
8 |
9 | const handleInputChange = (e: React.ChangeEvent) => {
10 | setInputValue(e.target.value);
11 | };
12 |
13 | return (
14 | <>
15 |
16 | Debounced Value: {debouncedValue}
17 | >
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/src/hooks/useDebounce/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: function
4 | title: useDebounce
5 | description: The useDebounce hook is a custom React hook that debounces the value and returns the latest value only after a specified delay of inactivity. It is useful for reducing the frequency of value updates in scenarios like user input or search input fields, where you want to delay processing the latest value until the user has paused for a specific time.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useDebounce/index.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | const useDebounce = (value: T, delay: number): T => {
4 | const [debouncedValue, setDebouncedValue] = useState(value);
5 |
6 | useEffect(() => {
7 | const debounceTimer = setTimeout(() => {
8 | setDebouncedValue(value);
9 | }, delay);
10 |
11 | return () => clearTimeout(debounceTimer);
12 | }, [value, delay]);
13 |
14 | return debouncedValue;
15 | };
16 |
17 | export default useDebounce;
18 |
--------------------------------------------------------------------------------
/src/hooks/useEvent/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEvent } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [clickCount, setClickCount] = useState(0);
7 |
8 | const handleClick = () => {
9 | setClickCount((prevCount) => prevCount + 1);
10 | };
11 |
12 | useEvent('click', handleClick);
13 |
14 | return (
15 | <>
16 | Click Counter
17 |
18 | Click Count: {clickCount}
19 | >
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/src/hooks/useEvent/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: device
3 | group: hooks
4 | title: useEvent
5 | description: The useEvent hook is a custom React hook that allows you to subscribe to and handle various events, including keyboard and mouse events. It takes an event name and a callback function as parameters and attaches the event listener to the specified element (default is window). This hook is useful for handling event-related logic in React components.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useEvent/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | type EventCallback = (event: Event) => void;
4 |
5 | const useEvent = (
6 | eventName: string,
7 | handler: EventCallback,
8 | element: HTMLElement | Window = window,
9 | ): void => {
10 | const savedHandler = useRef();
11 |
12 | useEffect(() => {
13 | savedHandler.current = handler;
14 | }, [handler]);
15 |
16 | useEffect(() => {
17 | const isSupported = element && element.addEventListener;
18 | if (!isSupported) return;
19 |
20 | const eventListener = (event: Event) => {
21 | if (savedHandler.current) {
22 | savedHandler.current(event);
23 | }
24 | };
25 |
26 | element.addEventListener(eventName, eventListener);
27 |
28 | return () => {
29 | element.removeEventListener(eventName, eventListener);
30 | };
31 | }, [eventName, element]);
32 | };
33 |
34 | export default useEvent;
35 |
--------------------------------------------------------------------------------
/src/hooks/useFileDownloader/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useFileDownloader } from '@dext7r/hooks';
2 | import { Button, Form, Input, message } from 'antd';
3 |
4 | const FileDownloader = () => {
5 | const { downloadFile } = useFileDownloader();
6 |
7 | const handleDownload = (values: { fileUrl: any; filename: any }) => {
8 | const { fileUrl, filename } = values;
9 | downloadFile(fileUrl, filename || 'downloaded_file').catch((error) => {
10 | console.error('下载文件时出现错误:', error);
11 | message.error('文件下载失败');
12 | });
13 | };
14 |
15 | return (
16 |
17 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 |
51 | );
52 | };
53 |
54 | export default FileDownloader;
55 |
--------------------------------------------------------------------------------
/src/hooks/useFileDownloader/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useFileDownloader
5 | description: useFileDownloader is a custom React Hook designed to enable file downloads within React components. It allows users to trigger file downloads by providing a file URL and an optional filename. The hook utilizes the fetch API to fetch the file from the given URL and initiates the download using an anchor (a) element without the need for streamsaver or CORS proxies. This hook offers a convenient way to implement file downloads in React components.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useFileDownloader/index.tsx:
--------------------------------------------------------------------------------
1 | import { message } from 'antd';
2 | import { useCallback } from 'react';
3 |
4 | const useFileDownloader = () => {
5 | const downloadFile = useCallback(async (fileUrl: RequestInfo | URL, filename: string) => {
6 | try {
7 | const response = await fetch(fileUrl);
8 | if (!response.ok) {
9 | throw new Error('下载文件时出错');
10 | }
11 |
12 | const blob = await response.blob();
13 | const url = URL.createObjectURL(blob);
14 |
15 | // Create a temporary anchor element
16 | const anchor = document.createElement('a');
17 | anchor.href = url;
18 | anchor.download = filename || 'downloaded_file';
19 | anchor.target = '_blank';
20 | document.body.appendChild(anchor);
21 |
22 | // Trigger the download
23 | anchor.click();
24 |
25 | // Clean up after the download is complete
26 | URL.revokeObjectURL(url);
27 | document.body.removeChild(anchor);
28 |
29 | message.success('文件下载成功');
30 | } catch (error) {
31 | console.error('下载文件时出现错误:', error);
32 | message.error('文件下载失败');
33 | }
34 | }, []);
35 |
36 | return { downloadFile };
37 | };
38 |
39 | export default useFileDownloader;
40 |
--------------------------------------------------------------------------------
/src/hooks/useFirstMountState/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useFirstMountState } from '@dext7r/hooks';
2 | import { Alert } from 'antd';
3 |
4 | export default () => {
5 | const isFirstMount = useFirstMountState();
6 |
7 | return (
8 | <>
9 | {isFirstMount && }
10 | Component content goes here.
11 | >
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/src/hooks/useFirstMountState/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useFirstMountState
5 | description: The useFirstMountState hook is a custom React hook that returns true if the component is just mounted (on the first render) and false on subsequent renders. It is useful for conditionally rendering content or performing actions only on the first render of a component.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useFirstMountState/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const useFirstMountState = (): boolean => {
4 | const isFirstMountRef = useRef(true);
5 |
6 | useEffect(() => {
7 | isFirstMountRef.current = false;
8 | }, []);
9 |
10 | return isFirstMountRef.current;
11 | };
12 |
13 | export default useFirstMountState;
14 |
--------------------------------------------------------------------------------
/src/hooks/useGeolocation/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useGeolocation } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const { latitude, longitude, error } = useGeolocation();
6 |
7 | useEffect(() => {
8 | if (error) {
9 | console.error('Error fetching geolocation:', error);
10 | } else {
11 | console.log('Latitude:', latitude);
12 | console.log('Longitude:', longitude);
13 | }
14 | }, [error, latitude, longitude]);
15 |
16 | return (
17 | <>
18 | Geolocation Data
19 | {error ? Error: {error}
: null}
20 | Latitude: {latitude}
21 | Longitude: {longitude}
22 | >
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/hooks/useGeolocation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: device
3 | group: hooks
4 | title: useGeolocation
5 | description: The useGeolocation hook is a custom React hook that allows you to fetch the user's current geolocation. It returns an object with latitude and longitude properties representing the current geolocation information or any errors that occurred during geolocation retrieval. This hook is useful for applications that require the user's geolocation data for location-based features.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useGeolocation/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | interface GeolocationPositionState {
4 | latitude: number;
5 | longitude: number;
6 | error: string | null;
7 | }
8 |
9 | const useGeolocation = (): GeolocationPositionState => {
10 | const [position, setPosition] = useState({
11 | latitude: 0,
12 | longitude: 0,
13 | error: null,
14 | });
15 |
16 | useEffect(() => {
17 | const successHandler = (position: GeolocationPosition) => {
18 | setPosition({
19 | latitude: position.coords.latitude,
20 | longitude: position.coords.longitude,
21 | error: null,
22 | });
23 | };
24 |
25 | const errorHandler = () => {
26 | setPosition({
27 | latitude: 0,
28 | longitude: 0,
29 | error: 'Geolocation API is not supported in this browser.',
30 | });
31 | };
32 |
33 | const options: PositionOptions = {
34 | enableHighAccuracy: true,
35 | timeout: 5000,
36 | maximumAge: 0,
37 | };
38 |
39 | const geo = navigator.geolocation;
40 | if (geo) {
41 | geo.getCurrentPosition(successHandler, errorHandler, options);
42 | } else {
43 | setPosition({
44 | latitude: 0,
45 | longitude: 0,
46 | error: 'Geolocation API is not supported in this browser.',
47 | });
48 | }
49 | }, []);
50 |
51 | return position;
52 | };
53 |
54 | export default useGeolocation;
55 |
--------------------------------------------------------------------------------
/src/hooks/useHover/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useHover } from '@dext7r/hooks';
2 | import { useRef } from 'react';
3 |
4 | export default () => {
5 | const elementRef = useRef(null);
6 | const isHovered = useHover(elementRef);
7 |
8 | return (
9 | <>
10 |
14 | {isHovered ? 'Hovering' : 'Not Hovering'}
15 |
16 | >
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/src/hooks/useHover/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useHover
5 | description: The useHover hook is a custom React hook that detects whether an element is currently being hovered over. It uses the mouseenter and mouseleave events for accurate hover detection.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useHover/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | const useHover = (elementRef: React.RefObject): boolean => {
4 | const [isHovered, setIsHovered] = useState(false);
5 |
6 | const handleMouseEnter = () => {
7 | setIsHovered(true);
8 | };
9 |
10 | const handleMouseLeave = () => {
11 | setIsHovered(false);
12 | };
13 |
14 | useEffect(() => {
15 | const element = elementRef.current;
16 | if (element) {
17 | element.addEventListener('mouseenter', handleMouseEnter);
18 | element.addEventListener('mouseleave', handleMouseLeave);
19 | return () => {
20 | element.removeEventListener('mouseenter', handleMouseEnter);
21 | element.removeEventListener('mouseleave', handleMouseLeave);
22 | };
23 | }
24 | }, [elementRef]);
25 |
26 | return isHovered;
27 | };
28 |
29 | export default useHover;
30 |
--------------------------------------------------------------------------------
/src/hooks/useHoverDirty/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useHoverDirty } from '@dext7r/hooks';
2 | import { useRef } from 'react';
3 |
4 | export default () => {
5 | const elementRef = useRef(null);
6 | const isHovered = useHoverDirty(elementRef);
7 |
8 | return (
9 | <>
10 |
14 | {isHovered ? 'Hovering' : 'Not Hovering'}
15 |
16 | >
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/src/hooks/useHoverDirty/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useHoverDirty
5 | description: The useHoverDirty hook is a custom React hook that detects whether an element is currently being hovered over. It uses the mouseover and mouseout events for less accurate but more performant hover detection.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useHoverDirty/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useState } from 'react';
2 |
3 | const useHoverDirty = (elementRef: React.RefObject): boolean => {
4 | const [isHovered, setIsHovered] = useState(false);
5 | const isHoveredRef = useRef(false);
6 |
7 | const handleMouseOver = () => {
8 | if (!isHoveredRef.current) {
9 | setIsHovered(true);
10 | isHoveredRef.current = true;
11 | }
12 | };
13 |
14 | const handleMouseOut = () => {
15 | if (isHoveredRef.current) {
16 | setIsHovered(false);
17 | isHoveredRef.current = false;
18 | }
19 | };
20 |
21 | useEffect(() => {
22 | const element = elementRef.current;
23 | if (element) {
24 | element.addEventListener('mouseover', handleMouseOver);
25 | element.addEventListener('mouseout', handleMouseOut);
26 | return () => {
27 | element.removeEventListener('mouseover', handleMouseOver);
28 | element.removeEventListener('mouseout', handleMouseOut);
29 | };
30 | }
31 | }, [elementRef]);
32 |
33 | return isHovered;
34 | };
35 | export default useHoverDirty;
36 |
--------------------------------------------------------------------------------
/src/hooks/useIdle/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useIdle } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const isIdle = useIdle(3000); // Set the timeout to 3 seconds (3000 milliseconds)
6 |
7 | useEffect(() => {
8 | if (isIdle) {
9 | console.log('User is idle.');
10 | } else {
11 | console.log('User is active.');
12 | }
13 | }, [isIdle]);
14 |
15 | return (
16 | <>
17 | Idle Detection
18 | User is {isIdle ? 'idle' : 'active'}
19 | >
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/src/hooks/useIdle/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useIdle
5 | description: The useIdle hook is a custom React hook that checks whether the user is idle using the requestIdleCallback API. It takes a timeout parameter to specify the duration after which the user is considered idle. This hook is useful for implementing idle-time related functionality in React applications.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useIdle/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | const useIdle = (timeout: number): boolean => {
4 | const [isIdle, setIsIdle] = useState(false);
5 |
6 | useEffect(() => {
7 | let idleTimer: number;
8 |
9 | const handleIdle = (deadline: IdleDeadline) => {
10 | if (deadline.timeRemaining() > 0) {
11 | setIsIdle(true);
12 | }
13 | };
14 |
15 | const handleActive = () => {
16 | setIsIdle(false);
17 | // Request the next idle callback after the specified timeout
18 | idleTimer = requestIdleCallback(handleIdle, { timeout });
19 | };
20 |
21 | // Initial idle check when the component mounts
22 | idleTimer = requestIdleCallback(handleIdle, { timeout });
23 |
24 | // Attach event listeners for activity detection
25 | document.addEventListener('mousemove', handleActive);
26 | document.addEventListener('keydown', handleActive);
27 | document.addEventListener('visibilitychange', handleActive);
28 |
29 | return () => {
30 | // Cleanup: remove event listeners and cancel any pending idle callbacks
31 | document.removeEventListener('mousemove', handleActive);
32 | document.removeEventListener('keydown', handleActive);
33 | document.removeEventListener('visibilitychange', handleActive);
34 | cancelIdleCallback(idleTimer);
35 | };
36 | }, [timeout]);
37 |
38 | return isIdle;
39 | };
40 |
41 | export default useIdle;
42 |
--------------------------------------------------------------------------------
/src/hooks/useInterval/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useInterval } from '@dext7r/hooks';
2 | import { useState } from 'react';
3 |
4 | export default () => {
5 | const [count, setCount] = useState(0);
6 |
7 | const intervalCallback = () => {
8 | setCount(count + 1);
9 | };
10 |
11 | useInterval(intervalCallback, 1000);
12 |
13 | return count: {count}
;
14 | };
15 |
--------------------------------------------------------------------------------
/src/hooks/useInterval/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: function
4 | title: useInterval
5 | description: The useInterval hook is a custom React hook that creates a declarative interval based on Dan Abramov's article on overreacted.io. It allows you to execute a callback function repeatedly at a specified time interval. The interval can be paused by setting the delay to null.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useInterval/index.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const useInterval = (callback: () => void, delay: number | null) => {
4 | const savedCallback = useRef<() => void>();
5 |
6 | // Save the latest callback to the ref
7 | useEffect(() => {
8 | savedCallback.current = callback;
9 | }, [callback]);
10 |
11 | useEffect(() => {
12 | const tick = () => {
13 | if (savedCallback.current) {
14 | savedCallback.current();
15 | }
16 | };
17 |
18 | if (delay !== null) {
19 | const intervalId = setInterval(tick, delay);
20 |
21 | return () => {
22 | clearInterval(intervalId);
23 | };
24 | }
25 | }, [delay]);
26 | };
27 |
28 | export default useInterval;
29 |
--------------------------------------------------------------------------------
/src/hooks/useLatest/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useLatest } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 | import React from 'react';
4 |
5 | export default () => {
6 | const [count, setCount] = React.useState(0);
7 |
8 | const latestCountRef = useLatest(count);
9 |
10 | const handleClick = () => {
11 | setCount(count + 1);
12 | };
13 |
14 | return (
15 |
16 |
朱砂痣久难消,你是否能知道: {latestCountRef.current}
17 |
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/src/hooks/useLatest/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useLatest
5 | description: useLatest is a custom hook in React that returns a reference to the latest value provided. It helps avoid capturing stale values in closures, making it useful for scenarios involving asynchronous operations or event handlers.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useLatest/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react';
2 |
3 | const useLatest = (value: T): { readonly current: T } => {
4 | const ref = useRef(value);
5 | ref.current = value;
6 |
7 | return ref;
8 | };
9 |
10 | export default useLatest;
11 |
--------------------------------------------------------------------------------
/src/hooks/useLocal/demos/index.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/src/hooks/useLocal/demos/index.tsx
--------------------------------------------------------------------------------
/src/hooks/useLocal/index.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/src/hooks/useLocal/index.md
--------------------------------------------------------------------------------
/src/hooks/useLocal/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/src/hooks/useLocal/index.ts
--------------------------------------------------------------------------------
/src/hooks/useLocal/index.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/src/hooks/useLocal/index.tsx
--------------------------------------------------------------------------------
/src/hooks/useLocalStorage/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useLocalStorage } from '@dext7r/hooks';
2 | import { Button, Input, message } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [inputValue, setInputValue] = useState('');
7 | const [customKey, setCustomKey] = useState(''); // Set the initial custom key to an empty string
8 | const [storedValue, setValue, getValue, deleteValue] = useLocalStorage(customKey, ''); // Pass the custom key to useLocalStorage hook
9 |
10 | const handleInputChange = (e: React.ChangeEvent) => {
11 | setInputValue(e.target.value);
12 | };
13 |
14 | const handleSave = () => {
15 | if (customKey === '') {
16 | message.error('Please enter a custom key before saving to localStorage.');
17 | } else {
18 | setValue(inputValue);
19 | message.success('Value saved to localStorage!');
20 | }
21 | };
22 |
23 | const handleGet = () => {
24 | if (customKey === '') {
25 | message.error('Please enter a custom key before getting from localStorage.');
26 | } else {
27 | const value = getValue();
28 | message.info(`Value from localStorage: ${value}`);
29 | }
30 | };
31 |
32 | const handleDelete = () => {
33 | if (customKey === '') {
34 | message.error('Please enter a custom key before deleting from localStorage.');
35 | } else {
36 | deleteValue();
37 | message.success('Value deleted from localStorage!');
38 | }
39 | };
40 |
41 | const handleCustomKeyChange = (e: React.ChangeEvent) => {
42 | setCustomKey(e.target.value);
43 | };
44 |
45 | return (
46 | <>
47 |
53 |
59 |
62 |
65 |
66 | Stored Value: {storedValue}
67 | >
68 | );
69 | };
70 |
--------------------------------------------------------------------------------
/src/hooks/useLocalStorage/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: store
4 | title: useLocalStorage
5 | description: The useLocalStorage hook is a custom React hook that manages a single localStorage key and synchronizes its value with the component's state. It provides an array containing the current value of the localStorage key and a function to update its value. This hook is useful for storing and retrieving data from the localStorage in a React component, ensuring that the component state and the localStorage value stay in sync.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useLocalStorage/index.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | const useLocalStorage = (
4 | key: string,
5 | initialValue: T,
6 | ): [T, (value: T) => void, () => T, () => void] => {
7 | const getLocalStorageValue = (): T => {
8 | try {
9 | const item = localStorage.getItem(key);
10 | return item ? JSON.parse(item) : initialValue;
11 | } catch (error) {
12 | console.error(`Error parsing localStorage item with key "${key}":`, error);
13 | return initialValue;
14 | }
15 | };
16 |
17 | const [storedValue, setStoredValue] = useState(getLocalStorageValue);
18 |
19 | const setValue = useCallback(
20 | (value: T) => {
21 | try {
22 | setStoredValue(value);
23 | localStorage.setItem(key, JSON.stringify(value));
24 | } catch (error) {
25 | console.error(`Error setting localStorage item with key "${key}":`, error);
26 | }
27 | },
28 | [key],
29 | );
30 |
31 | const getValue = useCallback((): T => {
32 | return getLocalStorageValue();
33 | }, []);
34 |
35 | const deleteValue = useCallback(() => {
36 | try {
37 | setStoredValue(initialValue);
38 | localStorage.removeItem(key);
39 | } catch (error) {
40 | console.error(`Error deleting localStorage item with key "${key}":`, error);
41 | }
42 | }, [initialValue, key]);
43 |
44 | return [storedValue, setValue, getValue, deleteValue];
45 | };
46 |
47 | export default useLocalStorage;
48 |
--------------------------------------------------------------------------------
/src/hooks/useLocation/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useLocation } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const { latitude, longitude, error } = useLocation();
6 |
7 | useEffect(() => {
8 | if (error) {
9 | console.error('Error fetching location:', error);
10 | } else {
11 | console.log('Latitude:', latitude);
12 | console.log('Longitude:', longitude);
13 | }
14 | }, [error, latitude, longitude]);
15 |
16 | return (
17 | <>
18 | Location Data
19 | {error ? Error: {error}
: null}
20 | Latitude: {latitude}
21 | Longitude: {longitude}
22 | >
23 | );
24 | };
25 |
--------------------------------------------------------------------------------
/src/hooks/useLocation/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useLocation
5 | description: The useLocation hook is a custom React hook that allows you to access and manage location data in your React application. It returns an object with latitude and longitude properties representing the location data or any errors that occurred during location retrieval. This hook is useful for applications that require the user's geolocation for location-based features.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useLocation/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | interface LocationState {
4 | latitude: number | null;
5 | longitude: number | null;
6 | error: string | null;
7 | }
8 |
9 | const useLocation = (): LocationState => {
10 | const [location, setLocation] = useState({
11 | latitude: null,
12 | longitude: null,
13 | error: null,
14 | });
15 |
16 | useEffect(() => {
17 | const successHandler = (position: GeolocationPosition) => {
18 | setLocation({
19 | latitude: position.coords.latitude,
20 | longitude: position.coords.longitude,
21 | error: null,
22 | });
23 | };
24 |
25 | const errorHandler = () => {
26 | setLocation({
27 | latitude: null,
28 | longitude: null,
29 | error: 'Error getting location data.',
30 | });
31 | };
32 |
33 | const options: PositionOptions = {
34 | enableHighAccuracy: true,
35 | timeout: 5000,
36 | maximumAge: 0,
37 | };
38 |
39 | const geo = navigator.geolocation;
40 | if (geo) {
41 | geo.getCurrentPosition(successHandler, errorHandler, options);
42 | } else {
43 | setLocation({
44 | latitude: null,
45 | longitude: null,
46 | error: 'Geolocation API is not supported in this browser.',
47 | });
48 | }
49 | }, []);
50 |
51 | return location;
52 | };
53 |
54 | export default useLocation;
55 |
--------------------------------------------------------------------------------
/src/hooks/useMeasure/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMeasure } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const [ref, size] = useMeasure();
6 |
7 | useEffect(() => {
8 | console.log('Width:', size.width);
9 | console.log('Height:', size.height);
10 | }, [size]);
11 |
12 | return (
13 | <>
14 | Element Size
15 |
16 | >
17 | );
18 | };
19 |
--------------------------------------------------------------------------------
/src/hooks/useMeasure/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useMeasure
5 | description: The useMeasure hook is a custom React hook that allows you to get the size (width and height) of an element. It returns a ref and a size object containing the current width and height of the element. This hook is useful for situations where you need to dynamically adjust components based on their dimensions or for responsive layouts.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useMeasure/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useState } from 'react';
2 |
3 | interface Size {
4 | width: number;
5 | height: number;
6 | }
7 |
8 | const useMeasure = (): [React.RefObject, Size] => {
9 | const ref = useRef(null);
10 | const [size, setSize] = useState({ width: 0, height: 0 });
11 |
12 | useEffect(() => {
13 | const handleResize = () => {
14 | if (ref.current) {
15 | const { width, height } = ref.current.getBoundingClientRect();
16 | setSize({ width, height });
17 | }
18 | };
19 |
20 | handleResize(); // Initial size update
21 | window.addEventListener('resize', handleResize);
22 |
23 | return () => {
24 | window.removeEventListener('resize', handleResize);
25 | };
26 | }, []);
27 |
28 | return [ref, size];
29 | };
30 |
31 | export default useMeasure;
32 |
--------------------------------------------------------------------------------
/src/hooks/useMedia/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMedia } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const isSmallScreen = useMedia('(max-width: 768px)'); // Check if the screen is smaller than 768px
6 |
7 | useEffect(() => {
8 | if (isSmallScreen) {
9 | console.log('Small screen detected.');
10 | } else {
11 | console.log('Large screen detected.');
12 | }
13 | }, [isSmallScreen]);
14 |
15 | return (
16 | <>
17 | Media Query Check
18 | Screen size: {isSmallScreen ? 'Small' : 'Large'}
19 | >
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/src/hooks/useMedia/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useMedia
5 | description: The useMedia hook is a custom React hook that allows you to check CSS media queries in your React application. It takes a CSS media query as input and returns a boolean value indicating whether the media query matches the current viewport size. This hook is useful for implementing responsive behavior in React components based on different screen sizes.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useMedia/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | const useMedia = (query: string): boolean => {
4 | const [matches, setMatches] = useState(false);
5 |
6 | useEffect(() => {
7 | const mediaQuery = window.matchMedia(query);
8 |
9 | const handleChange = (event: MediaQueryListEvent) => {
10 | setMatches(event.matches);
11 | };
12 |
13 | setMatches(mediaQuery.matches);
14 |
15 | mediaQuery.addListener(handleChange);
16 |
17 | return () => {
18 | mediaQuery.removeListener(handleChange);
19 | };
20 | }, [query]);
21 |
22 | return matches;
23 | };
24 |
25 | export default useMedia;
26 |
--------------------------------------------------------------------------------
/src/hooks/useMediaDevices/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMediaDevices } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const mediaDevices = useMediaDevices();
6 |
7 | useEffect(() => {
8 | console.log('Connected media devices:', mediaDevices);
9 | }, [mediaDevices]);
10 |
11 | return (
12 | <>
13 | Connected Media Devices
14 | {mediaDevices.length === 0 ? (
15 | No media devices found.
16 | ) : (
17 |
18 | {mediaDevices.map((device) => (
19 | -
20 | {device.label} ({device.kind})
21 |
22 | ))}
23 |
24 | )}
25 | >
26 | );
27 | };
28 |
--------------------------------------------------------------------------------
/src/hooks/useMediaDevices/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: device
3 | group: hooks
4 | title: useMediaDevices
5 | description: The useMediaDevices hook is a custom React hook that allows you to get information about connected media devices, such as cameras and microphones. It returns an array of MediaDeviceInfo objects, each containing the deviceId, kind, and label of the connected media device. This hook is useful for applications that require access to media devices and want to provide users with information about available devices.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useMediaDevices/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | interface MediaDeviceInfo {
4 | deviceId: string;
5 | kind: string;
6 | label: string;
7 | }
8 |
9 | const useMediaDevices = (): MediaDeviceInfo[] => {
10 | const [mediaDevices, setMediaDevices] = useState([]);
11 |
12 | useEffect(() => {
13 | const getMediaDevices = async () => {
14 | try {
15 | const devices = await navigator.mediaDevices.enumerateDevices();
16 | const mediaDeviceInfos: MediaDeviceInfo[] = devices.map((device) => ({
17 | deviceId: device.deviceId,
18 | kind: device.kind,
19 | label: device.label,
20 | }));
21 | setMediaDevices(mediaDeviceInfos);
22 | } catch (error) {
23 | console.error('Error enumerating media devices:', error);
24 | setMediaDevices([]);
25 | }
26 | };
27 |
28 | getMediaDevices();
29 |
30 | // Add event listener to detect changes in media devices (e.g., when a new device is connected)
31 | const handleDeviceChange = () => {
32 | getMediaDevices();
33 | };
34 | navigator.mediaDevices.addEventListener('devicechange', handleDeviceChange);
35 |
36 | return () => {
37 | navigator.mediaDevices.removeEventListener('devicechange', handleDeviceChange);
38 | };
39 | }, []);
40 |
41 | return mediaDevices;
42 | };
43 |
44 | export default useMediaDevices;
45 |
--------------------------------------------------------------------------------
/src/hooks/useMount/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMount } from '@dext7r/hooks';
2 | import { useState } from 'react';
3 |
4 | export default () => {
5 | const [message, setMessage] = useState('');
6 | useMount(() => {
7 | setMessage('人生如若初见,何事秋风悲画扇!');
8 | });
9 |
10 | return {message}
;
11 | };
12 |
--------------------------------------------------------------------------------
/src/hooks/useMount/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useMount
5 | description: useMount is a custom React Hook that executes a provided function once when the component mounts. It is similar to the componentDidMount lifecycle method and is useful for performing initialization logic or executing side effects that should occur only when the component mounts.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useMount/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 |
3 | const useMount = (fn: () => void) => {
4 | useEffect(() => {
5 | fn?.();
6 | }, []);
7 | };
8 |
9 | export default useMount;
10 |
--------------------------------------------------------------------------------
/src/hooks/useMountedState/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMountedState } from '@dext7r/hooks';
2 | import { message } from 'antd';
3 | import { useEffect } from 'react';
4 |
5 | export default () => {
6 | const isMounted = useMountedState();
7 |
8 | useEffect(() => {
9 | if (isMounted()) {
10 | message.info('Component is mounted.');
11 | } else {
12 | message.warning('Component is not mounted.');
13 | }
14 | }, [isMounted]);
15 |
16 | return Component Lifecycle Example
;
17 | };
18 |
--------------------------------------------------------------------------------
/src/hooks/useMountedState/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: lifecycle
4 | title: useMountedState
5 | description: The useMountedState hook is a custom React lifecycle hook that provides the ability to check the component's mount state. It returns a function that will return true if the component is mounted and false otherwise.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useMountedState/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const useMountedState = () => {
4 | const mountedRef = useRef(false);
5 |
6 | useEffect(() => {
7 | mountedRef.current = true;
8 | return () => {
9 | mountedRef.current = false;
10 | };
11 | }, []);
12 |
13 | return () => mountedRef.current;
14 | };
15 |
16 | export default useMountedState;
17 |
--------------------------------------------------------------------------------
/src/hooks/useNetwork/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useNetwork } from '@dext7r/hooks';
2 | import { useEffect } from 'react';
3 |
4 | export default () => {
5 | const { online, rtt, type, saveData, downlinkMax, effectiveType } = useNetwork();
6 |
7 | useEffect(() => {
8 | console.log('Online:', online);
9 | }, [online]);
10 |
11 | return (
12 | <>
13 | Network Connection Status
14 | Online: {online ? 'Yes' : 'No'}
15 | RTT: {rtt}
16 | Type: {type}
17 | Save Data: {saveData ? 'Yes' : 'No'}
18 | Downlink Max: {downlinkMax}
19 | Effective Type: {effectiveType}
20 | >
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/src/hooks/useNetwork/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useNetwork
5 | description: The useNetwork hook is a custom React hook that allows you to get information about the network connection status. It returns an object with online and type properties. The online property is a boolean indicating whether the device is connected to the internet, and the type property provides information about the network connection type. This hook is useful for applications that need to react to changes in the network connection status or display network-related information to users.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useNetwork/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | interface NetworkState {
4 | online?: boolean;
5 | rtt?: number;
6 | type?: 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown';
7 | saveData?: boolean;
8 | downlinkMax?: number;
9 | effectiveType?: 'slow-2g' | '2g' | '3g' | '4g';
10 | }
11 |
12 | const getConnection = (): NetworkState | undefined => {
13 | if (navigator && typeof navigator === 'object') {
14 | const nav = navigator as any;
15 | return {
16 | rtt: nav.connection?.rtt,
17 | type: nav.connection?.type || 'unknown',
18 | saveData: nav.connection?.saveData,
19 | downlinkMax: nav.connection?.downlinkMax || 0,
20 | effectiveType: nav.connection?.effectiveType,
21 | };
22 | }
23 | };
24 |
25 | const useNetwork = (): NetworkState => {
26 | // 获取网络状态信息
27 | const connection = getConnection();
28 | const [networkState, setNetworkState] = useState({
29 | online: navigator.onLine,
30 | ...connection,
31 | });
32 |
33 | useEffect(() => {
34 | const handleOnline = () => {
35 | setNetworkState((prevState) => ({ ...prevState, online: true }));
36 | };
37 |
38 | const handleOffline = () => {
39 | setNetworkState((prevState) => ({ ...prevState, online: false }));
40 | };
41 |
42 | window.addEventListener('online', handleOnline);
43 | window.addEventListener('offline', handleOffline);
44 |
45 | return () => {
46 | window.removeEventListener('online', handleOnline);
47 | window.removeEventListener('offline', handleOffline);
48 | };
49 | }, []);
50 |
51 | return networkState;
52 | };
53 |
54 | export default useNetwork;
55 |
--------------------------------------------------------------------------------
/src/hooks/usePrevious/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { usePrevious } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [count, setCount] = useState(0);
7 | const prevCount = usePrevious(count);
8 |
9 | const handleIncrement = () => {
10 | setCount((prevCount) => prevCount + 1);
11 | };
12 |
13 | return (
14 | <>
15 | Current Count: {count}
16 | Previous Count: {prevCount !== undefined ? prevCount : 'N/A'}
17 |
20 | >
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/src/hooks/usePrevious/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: usePrevious
5 | description: The usePrevious hook is a custom React hook that returns the previous state of a state variable. It utilizes the useRef and useEffect hooks to store and update the previous value whenever the state changes. This hook is helpful for tracking changes in state and performing actions based on the previous state value.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/usePrevious/index.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const usePrevious = (value: T): T | undefined => {
4 | const prevRef = useRef(undefined);
5 | const curRef = useRef(undefined);
6 |
7 | useEffect(() => {
8 | prevRef.current = curRef.current;
9 | curRef.current = value;
10 | });
11 |
12 | return prevRef.current;
13 | };
14 |
15 | export default usePrevious;
16 |
--------------------------------------------------------------------------------
/src/hooks/useRafState/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRafState } from '@dext7r/hooks';
2 | import { Card } from 'antd';
3 | import { useEffect } from 'react';
4 |
5 | const useMount = (callback: () => void) => {
6 | useEffect(() => {
7 | callback();
8 | }, []);
9 | };
10 |
11 | export default () => {
12 | const [state, setState] = useRafState({ x: 0, y: 0 });
13 |
14 | useMount(() => {
15 | const onMouseMove = (event: MouseEvent) => {
16 | setState({ x: event.clientX, y: event.clientY });
17 | };
18 | const onTouchMove = (event: TouchEvent) => {
19 | setState({
20 | x: event.changedTouches[0].clientX,
21 | y: event.changedTouches[0].clientY,
22 | });
23 | };
24 |
25 | document.addEventListener('mousemove', onMouseMove);
26 | document.addEventListener('touchmove', onTouchMove);
27 |
28 | return () => {
29 | document.removeEventListener('mousemove', onMouseMove);
30 | document.removeEventListener('touchmove', onTouchMove);
31 | };
32 | });
33 |
34 | return (
35 |
36 | {JSON.stringify(state, null, 2)}
37 |
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/src/hooks/useRafState/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: animation
4 | title: useRafState
5 | description: The useRafState hook is a custom React state hook that only updates state in the callback of requestAnimationFrame. This can be useful for optimizing animations and reducing unnecessary renders.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useRafState/index.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useRef, useState } from 'react';
2 |
3 | const useRafState = (initialState: T) => {
4 | const frame = useRef(0);
5 | const [state, setState] = useState(initialState);
6 |
7 | const setRafState = useCallback((value: T) => {
8 | cancelAnimationFrame(frame.current);
9 |
10 | frame.current = requestAnimationFrame(() => {
11 | setState(value);
12 | });
13 | }, []);
14 |
15 | return [state, setRafState] as const;
16 | };
17 |
18 | export default useRafState;
19 |
--------------------------------------------------------------------------------
/src/hooks/useSafeState/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useSafeState } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 | import { useEffect, useState } from 'react';
4 |
5 | const Child = () => {
6 | const [value, setValue] = useSafeState('二选一,别选我');
7 |
8 | useEffect(() => {
9 | setTimeout(() => {
10 | setValue('定时器3s后触发');
11 | }, 3000);
12 | }, []);
13 |
14 | const text = value || 'Loading...';
15 |
16 | return {text}
;
17 | };
18 |
19 | const Index = () => {
20 | const [flag, setFlag] = useState(false);
21 |
22 | return (
23 |
24 |
27 | {flag && }
28 |
29 | );
30 | };
31 |
32 | export default Index;
33 |
--------------------------------------------------------------------------------
/src/hooks/useSafeState/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useSafeState
5 | description: The useSafeState hook is a utility function in React that helps ensure safe state updates, even when a component is unmounted. It acts as an enhancement to the useState hook by checking if the component is still mounted before updating the state. This helps prevent potential memory leaks or errors caused by state updates in unmounted components.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useSafeState/index.tsx:
--------------------------------------------------------------------------------
1 | import type { Dispatch, SetStateAction } from 'react';
2 | import { useCallback, useState } from 'react';
3 | import useUnmountedRef from '../useUnmountedRef';
4 |
5 | function useSafeState(initialState: S | (() => S)): [S, Dispatch>];
6 | function useSafeState(): [S | undefined, Dispatch>];
7 | function useSafeState(initialState?: S | (() => S)) {
8 | const unmountedRef: { current: boolean } = useUnmountedRef();
9 | const [state, setState] = useState(initialState);
10 | const setCurrentState = useCallback((currentState: any) => {
11 | if (unmountedRef.current) return;
12 | setState(currentState);
13 | }, []);
14 |
15 | return [state, setCurrentState] as const;
16 | }
17 |
18 | export default useSafeState;
19 |
--------------------------------------------------------------------------------
/src/hooks/useSessionStorage/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useSessionStorage } from '@dext7r/hooks';
2 | import { Button, Input } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [inputValue, setInputValue] = useState('');
7 | const [storedValue, setValue] = useSessionStorage('example_key', ''); // Pass the sessionStorage key to useSessionStorage hook
8 |
9 | const handleInputChange = (e: React.ChangeEvent) => {
10 | setInputValue(e.target.value);
11 | };
12 |
13 | const handleSave = () => {
14 | setValue(inputValue);
15 | };
16 |
17 | return (
18 | <>
19 |
24 |
25 | Stored Value: {storedValue}
26 | >
27 | );
28 | };
29 |
--------------------------------------------------------------------------------
/src/hooks/useSessionStorage/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: store
4 | title: useSessionStorage
5 | description: The useSessionStorage hook is a custom React hook that manages a single sessionStorage key and synchronizes its value with the component's state. It provides an array containing the current value of the sessionStorage key and a function to update its value. This hook is useful for storing and retrieving data from the sessionStorage in a React component, ensuring that the component state and the sessionStorage value stay in sync within the same session.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useSessionStorage/index.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | const useSessionStorage = (key: string, initialValue: T): [T, (value: T) => void] => {
4 | const getSessionStorageValue = (): T => {
5 | try {
6 | const item = sessionStorage.getItem(key);
7 | return item ? JSON.parse(item) : initialValue;
8 | } catch (error) {
9 | console.error(`Error parsing sessionStorage item with key "${key}":`, error);
10 | return initialValue;
11 | }
12 | };
13 |
14 | const [storedValue, setStoredValue] = useState(getSessionStorageValue);
15 |
16 | const setValue = useCallback(
17 | (value: T) => {
18 | try {
19 | setStoredValue(value);
20 | sessionStorage.setItem(key, JSON.stringify(value));
21 | } catch (error) {
22 | console.error(`Error setting sessionStorage item with key "${key}":`, error);
23 | }
24 | },
25 | [key],
26 | );
27 |
28 | return [storedValue, setValue];
29 | };
30 |
31 | export default useSessionStorage;
32 |
--------------------------------------------------------------------------------
/src/hooks/useSessionStorage/index.tsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/src/hooks/useSessionStorage/index.tsx
--------------------------------------------------------------------------------
/src/hooks/useThrottle/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useThrottle } from '@dext7r/hooks';
2 | import { Input } from 'antd';
3 | import { useState } from 'react';
4 |
5 | export default () => {
6 | const [inputValue, setInputValue] = useState('');
7 | const throttledValue = useThrottle(inputValue, 500);
8 |
9 | const handleInputChange = (e: React.ChangeEvent) => {
10 | setInputValue(e.target.value);
11 | };
12 |
13 | return (
14 | <>
15 |
16 | Throttled Value: {throttledValue}
17 | >
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/src/hooks/useThrottle/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: function
4 | title: useThrottle
5 | description: The useThrottle hook is a custom React hook that throttles the value and returns the latest value at a specified interval. It is useful for reducing the frequency of value updates and improving performance for actions such as user input or state changes that trigger frequent renders.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useThrottle/index.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef, useState } from 'react';
2 |
3 | const useThrottle = (value: T, delay: number): T => {
4 | const [throttledValue, setThrottledValue] = useState(value);
5 | const timeoutRef = useRef(null);
6 | const previousValueRef = useRef(value);
7 |
8 | useEffect(() => {
9 | if (value !== previousValueRef.current) {
10 | previousValueRef.current = value;
11 | if (timeoutRef.current) {
12 | clearTimeout(timeoutRef.current);
13 | }
14 | timeoutRef.current = setTimeout(() => {
15 | setThrottledValue(value);
16 | }, delay);
17 | }
18 | }, [value, delay]);
19 |
20 | return throttledValue;
21 | };
22 |
23 | export default useThrottle;
24 |
--------------------------------------------------------------------------------
/src/hooks/useToggle/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useToggle } from '@dext7r/hooks';
2 | import { Button } from 'antd';
3 |
4 | export default () => {
5 | const [isToggled, toggle] = useToggle();
6 |
7 | return (
8 | <>
9 | 当前布尔值:{String(isToggled)}
10 |
13 | >
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/src/hooks/useToggle/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useToggle
5 | description: The useToggle hook is a custom React hook that simplifies the process of toggling a boolean value in a React component. It takes an initial boolean value and returns a tuple with the current boolean value and a function to toggle it. This hook makes it easy to handle toggling states in React components.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useToggle/index.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react';
2 |
3 | const useToggle = (initialValue: boolean = false): [boolean, () => void] => {
4 | const [value, setValue] = useState(initialValue);
5 |
6 | const toggle = useCallback(() => {
7 | setValue((prevValue) => !prevValue);
8 | }, []);
9 |
10 | return [value, toggle];
11 | };
12 |
13 | export default useToggle;
14 |
--------------------------------------------------------------------------------
/src/hooks/useUnmount/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useUnmount } from '@dext7r/hooks';
2 | import { message } from 'antd';
3 |
4 | export default () => {
5 | useUnmount(() => {
6 | message.success('useUnmount: 分手应该体面,谁都不要说抱歉');
7 | });
8 |
9 | return 'useUnmount只会在函数销毁后触发。切换到其他页面即可查看信息';
10 | };
11 |
--------------------------------------------------------------------------------
/src/hooks/useUnmount/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useUnmount
5 | description: useUnmount is a custom React Hook that executes a specified function when a component is unmounted.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useUnmount/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import useLatest from '../useLatest';
3 |
4 | const useUnmount = (fn: () => void) => {
5 | const fnRef = useLatest(fn);
6 |
7 | useEffect(
8 | () => () => {
9 | fnRef.current();
10 | },
11 | [],
12 | );
13 | };
14 |
15 | export default useUnmount;
16 |
--------------------------------------------------------------------------------
/src/hooks/useUnmountedRef/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useMount, useUnmount, useUnmountedRef } from '@dext7r/hooks';
2 | import { Button, message } from 'antd';
3 | import { useState } from 'react';
4 |
5 | const Child = () => {
6 | const unmountedRef = useUnmountedRef();
7 | useMount(() => {
8 | message.success('朱砂痣');
9 | console.log('初始化:', unmountedRef);
10 | });
11 | useUnmount(() => {
12 | message.success('白月光');
13 | console.log('卸载:', unmountedRef);
14 | });
15 |
16 | return 得不到的美好,总在心间挠
;
17 | };
18 |
19 | const Index = () => {
20 | const [flag, setFlag] = useState(false);
21 |
22 | return (
23 |
24 |
27 | {flag && }
28 |
29 | );
30 | };
31 |
32 | export default Index;
33 |
--------------------------------------------------------------------------------
/src/hooks/useUnmountedRef/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: hooks
4 | title: useUnmountedRef
5 | description: The useUnmountedRef Hook provides a reference to check if a component is unmounted.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useUnmountedRef/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | const useUnmountedRef = (): { readonly current: boolean } => {
4 | const unmountedRef = useRef(false);
5 |
6 | useEffect(() => {
7 | unmountedRef.current = false;
8 | return () => {
9 | unmountedRef.current = true;
10 | };
11 | }, []);
12 |
13 | return unmountedRef;
14 | };
15 |
16 | export default useUnmountedRef;
17 |
--------------------------------------------------------------------------------
/src/hooks/useVirtualList/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { useVirtualList } from '@dext7r/hooks';
2 | import { Input, List } from 'antd';
3 | import { useState } from 'react';
4 |
5 | const allItems = Array.from(Array(9999).keys()).map((i) => ({
6 | height: i % 2 === 0 ? 42 : 84,
7 | size: i % 2 === 0 ? 'small' : 'large',
8 | }));
9 |
10 | const virtualListOptions = {
11 | containerHeight: 400, // Set the height of the container as required
12 | itemHeight: 50, // Set the fixed height of each item or provide a function for dynamic height
13 | overscan: 10, // Set the number of extra buffer items outside of the view area
14 | };
15 |
16 | const VirtualListExample = () => {
17 | const [search, setSearch] = useState('');
18 |
19 | const filteredItems = allItems.filter((item) => item.size.startsWith(search.toLowerCase()));
20 |
21 | const { list, scrollTo, containerProps, wrapperProps } = useVirtualList(
22 | filteredItems,
23 | virtualListOptions,
24 | );
25 |
26 | return (
27 |
28 |
29 | {
32 | setSearch(e.target.value);
33 | scrollTo(0); // Scroll to the top when search filters are updated
34 | }}
35 | style={{ width: '20rem' }}
36 | />
37 |
38 |
39 |
40 | (
43 |
44 | Row {item.index} ({item.data.size})
45 |
46 | )}
47 | />
48 |
49 |
50 |
51 | );
52 | };
53 |
54 | export default VirtualListExample;
55 |
--------------------------------------------------------------------------------
/src/hooks/useVirtualList/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: hooks
3 | group: optimization
4 | title: useVirtualList
5 | description: The useVirtualList hook is a custom React hook that allows you to use a virtual list to render huge chunks of list data efficiently. It is essential to set a height for the container to enable virtualization.
6 | ---
7 |
8 | ## Default
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/hooks/useVirtualList/index.ts:
--------------------------------------------------------------------------------
1 | import { CSSProperties, RefObject, useMemo, useRef, useState } from 'react';
2 |
3 | export interface UseVirtualListOptions {
4 | containerHeight?: number;
5 | itemHeight: number | ((index: number) => number);
6 | overscan?: number;
7 | }
8 |
9 | export interface UseVirtualListItem {
10 | data: T;
11 | index: number;
12 | }
13 |
14 | export interface UseVirtualListReturn {
15 | list: UseVirtualListItem[];
16 | scrollTo: (index: number) => void;
17 | containerProps: {
18 | ref: RefObject;
19 | onScroll: () => void;
20 | style: Partial & { overflowY: 'auto' };
21 | };
22 | wrapperProps: {
23 | style: {
24 | width: string;
25 | height: string;
26 | marginTop: string;
27 | };
28 | };
29 | }
30 |
31 | export default function useVirtualList(
32 | list: T[] | undefined,
33 | options: UseVirtualListOptions,
34 | ): UseVirtualListReturn {
35 | const { containerHeight = 300, itemHeight, overscan = 5 } = options;
36 | const [scrollTop, setScrollTop] = useState(0);
37 |
38 | const totalHeight = useMemo(() => {
39 | if (!list) return 0;
40 | if (typeof itemHeight === 'number') {
41 | return list.length * itemHeight;
42 | }
43 | return list.reduce((acc, _, index) => acc + itemHeight(index), 0);
44 | }, [list, itemHeight]);
45 |
46 | const visibleCount = Math.ceil(
47 | containerHeight / (typeof itemHeight === 'number' ? itemHeight : 0),
48 | );
49 | const startIdx = Math.max(
50 | 0,
51 | Math.floor(scrollTop / (typeof itemHeight === 'number' ? itemHeight : 0)) - overscan,
52 | );
53 | const endIdx = Math.min(list ? list.length - 1 : 0, startIdx + visibleCount + 2 * overscan);
54 |
55 | const visibleData = useMemo(() => {
56 | if (!list) return [];
57 | return list.slice(startIdx, endIdx + 1).map((data, index) => ({
58 | data,
59 | index: startIdx + index,
60 | }));
61 | }, [list, startIdx, endIdx]);
62 |
63 | const containerRef = useRef(null);
64 |
65 | const handleScroll = () => {
66 | if (containerRef.current) {
67 | setScrollTop(containerRef.current.scrollTop);
68 | }
69 | };
70 |
71 | const scrollTo = (index: number) => {
72 | if (containerRef.current) {
73 | const itemHeightValue = typeof itemHeight === 'number' ? itemHeight : itemHeight(index);
74 | const scrollTop = index * itemHeightValue;
75 | containerRef.current.scrollTop = scrollTop;
76 | }
77 | };
78 |
79 | const containerProps = {
80 | ref: containerRef,
81 | onScroll: handleScroll,
82 | style: {
83 | height: `${containerHeight}px`,
84 | overflowY: 'auto',
85 | } as const,
86 | };
87 |
88 | const wrapperProps = {
89 | style: {
90 | width: '100%',
91 | height: `${totalHeight}px`,
92 | marginTop: `${startIdx * (typeof itemHeight === 'number' ? itemHeight : 0)}px`,
93 | },
94 | };
95 |
96 | return {
97 | list: visibleData,
98 | scrollTo,
99 | containerProps,
100 | wrapperProps,
101 | };
102 | }
103 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './hooks';
2 | export * from './utils';
3 |
--------------------------------------------------------------------------------
/src/utils/date/demos/index.tsx:
--------------------------------------------------------------------------------
1 | import { isYesterday } from '@dext7r/hooks';
2 | import { useEffect, useState } from 'react';
3 |
4 | export default () => {
5 | const [isYesterdayDate, setIsYesterdayDate] = useState(false);
6 | useEffect(() => {
7 | const flag = isYesterday(new Date());
8 | setIsYesterdayDate(flag);
9 | }, []);
10 |
11 | return (
12 | <>
13 | {isYesterdayDate ? 'Yesterday' : 'Not Yesterday'}
14 | >
15 | );
16 | };
17 |
--------------------------------------------------------------------------------
/src/utils/date/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | nav: utils
3 | group: date
4 | title: isYesterday
5 | description: The isYesterday function is used to determine if a given date is yesterday. It takes a date parameter (which can be a string, number, or Date object) and an optional integer parameter n to specify the relative date offset from the current date. The default value for n is 1, indicating yesterday. The function compares the provided date with the date of yesterday, and if they share the same year, month, and day, it returns true; otherwise, it returns false.
6 | ---
7 |
8 | Here's a detailed step-by-step explanation of the function:
9 |
10 | Get the current date and store it in the curDate variable. Calculate the target date (defaulted to yesterday) by subtracting n days.
11 | Create the tarDate variable to store the specified date based on the input date parameter. If no date parameter is provided, it defaults to the current date.
12 | Create a string array called dateProperties containing the property names of the date object, including 'getFullYear', 'getMonth', and 'getDate'.
13 | Use the .every function to iterate through each property name in the dateProperties array. For each property, store the corresponding property values of curDate and tarDate in variables and then compare them.
14 | Return the comparison result. If all property values are the same, indicating that the given date is yesterday, the function returns true; otherwise, it returns false.
15 |
16 | ## Default
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/utils/date/index.ts:
--------------------------------------------------------------------------------
1 | export default function isYesterday(date: string | Date | undefined, n = 1): boolean {
2 | const curDate = new Date(); // 当前日期
3 | curDate.setDate(curDate.getDate() - n); // 当前日期减n天
4 | // 指定日期
5 | const tarData = date
6 | ? new Date(typeof date === 'string' && date.includes('-') ? date.replace(/-/g, '/') : date)
7 | : new Date();
8 | return ['getFullYear', 'getMonth', 'getDate'].every(
9 | (i) => (curDate as any)[i]() === (tarData as any)[i](),
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/src/utils/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 工具集
3 | nav:
4 | title: utils
5 | order: 1
6 | apiHeader: false
7 | group:
8 | title: 介绍
9 | order: -1
10 | ---
11 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export { default as isYesterday } from './date';
2 |
--------------------------------------------------------------------------------
/tea.yaml:
--------------------------------------------------------------------------------
1 | # https://tea.xyz/what-is-this-file
2 | ---
3 | version: 1.0.0
4 | codeOwners:
5 | - '0xBC99fC607a02790fc46c7e77F55fECAb120B9896'
6 | quorum: 1
7 |
--------------------------------------------------------------------------------
/tests/test-setup.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/h7ml/hooks/c3d33099d9edf3e4e25c3ce6b6c70d4700db9589/tests/test-setup.ts
--------------------------------------------------------------------------------
/tsconfig-check.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src", "tests", ".dumirc.ts", "*.ts"],
3 | "compilerOptions": {
4 | "strict": true,
5 | "declaration": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "resolveJsonModule": true,
9 | "jsx": "react-jsx",
10 | "baseUrl": ".",
11 | "types": ["vitest/globals"],
12 | "paths": {
13 | "@@/*": [".dumi/tmp/*"],
14 | "@/*": ["src"],
15 | "@dext7r/hooks": ["src"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config';
2 | import { name } from './package.json';
3 |
4 | export default defineConfig({
5 | esbuild: {
6 | jsxInject: "import React from 'react'",
7 | },
8 | test: {
9 | setupFiles: './tests/test-setup.ts',
10 | environment: 'jsdom',
11 | globals: true,
12 | alias: {
13 | '@': './src',
14 | [name]: './src',
15 | },
16 | coverage: {
17 | reporter: ['text', 'text-summary', 'json', 'lcov'],
18 | },
19 | },
20 | });
21 |
--------------------------------------------------------------------------------