From 7cb7ea15f00b8818e5b10e6c640e59fc3a36fde4 Mon Sep 17 00:00:00 2001 From: Yuwang Cai Date: Fri, 22 Nov 2024 16:04:52 +0800 Subject: [PATCH] docs: add docs for several hooks (#11) --- docs/.vitepress/config.ts | 158 ++++++++++++++++++++++++++++++ docs/hooks/use-async-effect.md | 28 ++++++ docs/hooks/use-boolean.md | 54 ++++++++++ docs/hooks/use-click-outside.md | 25 +++++ docs/hooks/use-clipboard-text.md | 53 ++++++++++ docs/hooks/use-const-fn.md | 23 +++++ docs/hooks/use-const.md | 21 ++++ docs/hooks/use-counter.md | 61 ++++++++++++ docs/hooks/use-debounce-effect.md | 53 ++++++++++ docs/hooks/use-debounce.md | 46 +++++++++ src/use-async-effect.ts | 14 ++- src/use-boolean.ts | 40 +++++++- src/use-click-outside.ts | 7 ++ src/use-clipboard-text.ts | 44 ++++++++- src/use-const-fn.ts | 8 +- src/use-const.ts | 4 +- src/use-counter.ts | 7 ++ src/use-debounce-effect.ts | 23 +++++ src/use-debounce.ts | 23 +++++ 19 files changed, 685 insertions(+), 7 deletions(-) create mode 100644 docs/hooks/use-async-effect.md create mode 100644 docs/hooks/use-boolean.md create mode 100644 docs/hooks/use-click-outside.md create mode 100644 docs/hooks/use-clipboard-text.md create mode 100644 docs/hooks/use-const-fn.md create mode 100644 docs/hooks/use-const.md create mode 100644 docs/hooks/use-counter.md create mode 100644 docs/hooks/use-debounce-effect.md create mode 100644 docs/hooks/use-debounce.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 300b32d..dff48fe 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -39,6 +39,164 @@ export default defineConfig({ }, ], }, + { + text: "Hooks", + base: "/hooks", + items: [ + { + text: "useAsyncEffect", + link: "/use-async-effect", + }, + { + text: "useBoolean", + link: "/use-boolean", + }, + { + text: "useClickOutside", + link: "/use-click-outside", + }, + { + text: "useClipboardText", + link: "/use-clipboard-text", + }, + { + text: "useConstFn", + link: "/use-const-fn", + }, + { + text: "useConst", + link: "/use-const", + }, + { + text: "useCounter", + link: "/use-counter", + }, + { + text: "useDebounceEffect", + link: "/use-debounce-effect", + }, + { + text: "useDebounce", + link: "/use-debounce", + }, + { + text: "useDocumentEventListener", + link: "/use-document-event-listener", + }, + { + text: "useDocument", + link: "/use-document", + }, + { + text: "useElementSize", + link: "/use-element-size", + }, + { + text: "useEventListener", + link: "/use-event-listener", + }, + { + text: "useFocusTrap", + link: "/use-focus-trap", + }, + { + text: "useHover", + link: "/use-hover", + }, + { + text: "useInterval", + link: "/use-interval", + }, + { + text: "useIsMounted", + link: "/use-is-mounted", + }, + { + text: "useKeydown", + link: "/use-keydown", + }, + { + text: "useLatest", + link: "/use-latest", + }, + { + text: "useLocalStorage", + link: "/use-local-storage", + }, + { + text: "useMediaQuery", + link: "/use-media-query", + }, + { + text: "useMount", + link: "/use-mount", + }, + { + text: "usePrevious", + link: "/use-previous", + }, + { + text: "useRerender", + link: "/use-rerender", + }, + { + text: "useSafeLayoutEffect", + link: "/use-safe-layout-effect", + }, + { + text: "useSessionStorage", + link: "/use-session-storage", + }, + { + text: "useTextSelection", + link: "/use-text-selection", + }, + { + text: "useTheme", + link: "/use-theme", + }, + { + text: "useThrottleEffect", + link: "/use-throttle-effect", + }, + { + text: "useThrottle", + link: "/use-throttle", + }, + { + text: "useTimeout", + link: "/use-timeout", + }, + { + text: "useTitle", + link: "/use-title", + }, + { + text: "useToggle", + link: "/use-toggle", + }, + { + text: "useUnmount", + link: "/use-unmount", + }, + { + text: "useUnsafeOnceEffect", + link: "/use-unsafe-once-effect", + }, + { + text: "useUpdate", + link: "/use-update", + }, + { + text: "useWindowSize", + link: "/use-window-size", + }, + { + text: "useWindow", + link: "/use-window", + }, + ], + }, ], socialLinks: [ { diff --git a/docs/hooks/use-async-effect.md b/docs/hooks/use-async-effect.md new file mode 100644 index 0000000..ab79830 --- /dev/null +++ b/docs/hooks/use-async-effect.md @@ -0,0 +1,28 @@ +# useAsyncEffect + +Same as `useEffect`, but the effect can be asynchronous. + +```ts +useAsyncEffect(async () => { + await fetch("https://api.example.com/data"); +}, []); +``` + +## Parameters + +### effect + +- Type: `() => Promise` + +The asynchronous effect to run. + +> [!NOTE] +> +> Destructor is not yet supported. The cleanup function returned by the effect will be ignored and discarded. + +### deps + +- Type: `DependencyList` +- Default: `undefined` + +The dependencies of the effect, just like in `useEffect`. diff --git a/docs/hooks/use-boolean.md b/docs/hooks/use-boolean.md new file mode 100644 index 0000000..edcc155 --- /dev/null +++ b/docs/hooks/use-boolean.md @@ -0,0 +1,54 @@ +# useBoolean + +Use a boolean value. + +```ts +const { value, set, setTrue, setFalse, toggle, reset } = useBoolean(); +``` + +## Parameters + +### initialValue + +- Type: `boolean` +- Default: `false` + +The initial value of the boolean. + +## Returns + +### value + +- Type: `boolean` + +The current value of the boolean. + +### set + +- Type: `Dispatch>` + +Set the value to any boolean. + +### setTrue + +- Type: `() => void` + +Set the value to `true`. + +### setFalse + +- Type: `() => void` + +Set the value to `false`. + +### toggle + +- Type: `() => void` + +Toggle the value, that is, to set the value to `true` if it is currently `false`, and to `false` if it is currently `true`. + +### reset + +- Type: `() => void` + +Reset the value to the initial value. diff --git a/docs/hooks/use-click-outside.md b/docs/hooks/use-click-outside.md new file mode 100644 index 0000000..ae3fd42 --- /dev/null +++ b/docs/hooks/use-click-outside.md @@ -0,0 +1,25 @@ +# useClickOutside + +Listen to click events outside of a node. + +```ts +const modalRef = useRef(null); + +useClickOutside(modalRef, () => closeModal()); +``` + +## Parameters + +### ref + +- Type: `RefObject` + +The ref of the node to listen for click events outside of. + +### callback + +- Type: `(event: MouseEvent, target: Node) => void` + +The function to call when a click event occurs outside of the node. + +The first argument is the click event, and the second argument is the target node contained inside the `ref`. diff --git a/docs/hooks/use-clipboard-text.md b/docs/hooks/use-clipboard-text.md new file mode 100644 index 0000000..b38f0f2 --- /dev/null +++ b/docs/hooks/use-clipboard-text.md @@ -0,0 +1,53 @@ +# useClipboardText + +Use the text on the user's clipboard. + +```ts +const { text, error, write } = useClipboardText(); +``` + +## Parameters + +### options + +- Type: `UseClipboardTextOptions` +- Default: `{}` + +The options to configure the hook. + +## Options + +### readOnMount + +- Type: `boolean` +- Default: `true` + +Whether to immediately read the user's clipboard when the hook is mounted. + +If set to `false`, the returned `text` will be its default value, that is, `""`. + +When this option is changed from `false` to `true`, the hook will read the user's clipboard. + +## Returns + +### text + +- Type: `string` +- Default: `""` + +The text on the user's clipboard. + +### error + +- Type: `Error | null` +- Default: `null` + +The error that occurs while reading from or writing to the user's clipboard. + +After any successful read or write operation, `error` will be reset to `null`. + +### write + +- Type: `(text: string) => Promise` + +Write text to the user's clipboard. diff --git a/docs/hooks/use-const-fn.md b/docs/hooks/use-const-fn.md new file mode 100644 index 0000000..3b8134c --- /dev/null +++ b/docs/hooks/use-const-fn.md @@ -0,0 +1,23 @@ +# useConstFn + +Memoize a function, which stays the same across rerenders. + +```ts +const fn = useConstFn(() => { + doSomething(); +}); +``` + +## Parameters + +### fn + +- Type: `Function` + +The function to memoize. + +## Returns + +- Type: `Function` + +The memoized function. diff --git a/docs/hooks/use-const.md b/docs/hooks/use-const.md new file mode 100644 index 0000000..913e556 --- /dev/null +++ b/docs/hooks/use-const.md @@ -0,0 +1,21 @@ +# useConst + +Memoize a value, which stays the same across rerenders. + +```ts +const value = useConst(() => expensiveCompute()); +``` + +## Parameters + +### factory + +- Type: `() => T` + +A function that computes the value to be memoized. + +## Returns + +- Type: `T` + +The memoized value. diff --git a/docs/hooks/use-counter.md b/docs/hooks/use-counter.md new file mode 100644 index 0000000..e28b7d5 --- /dev/null +++ b/docs/hooks/use-counter.md @@ -0,0 +1,61 @@ +# useCounter + +Use a counter. + +```ts +const { count, set, increment, decrement, incrementBy, decrementBy, reset } = + useCounter(); +``` + +## Parameters + +### initialCount + +- Type: `number` +- Default: 0 + +The initial value of the counter. + +## Returns + +### count + +- Type: `number` + +The current value of the counter. + +### set + +- Type: `Dispatch>` + +Set the count to any number. + +### increment + +- Type: `() => void` + +Increment the count by 1. + +### decrement + +- Type: `() => void` + +Decrement the count by 1. + +### incrementBy + +- Type: `(delta: number) => void` + +Increment the count by a specified amount. + +### decrementBy + +- Type: `(delta: number) => void` + +Decrement the count by a specified amount. + +### reset + +- Type: `() => void` + +Reset the count to the initial count. diff --git a/docs/hooks/use-debounce-effect.md b/docs/hooks/use-debounce-effect.md new file mode 100644 index 0000000..4e7789e --- /dev/null +++ b/docs/hooks/use-debounce-effect.md @@ -0,0 +1,53 @@ +# useDebounceEffect + +Debounce an effect. + +```ts +useDebounceEffect( + () => { + doSomething(); + }, + [], + { timeout: 1000 }, +); +``` + +## Parameters + +### effect + +- Type: `EffectCallback` + +The effect to be debounced. + +### deps + +- Type: `DependencyList` +- Default: `undefined` + +The dependencies of the effect, just like in `useEffect`. + +### options + +- Type: `UseDebounceEffectOptions` +- Default: `{}` + +The options to configure the hook. + +## Options + +### timeout + +- Type: `number` +- Default: 500 + +The time in milliseconds between the last call of the effect and the actual execution. + +Changes of this value will clear the current timer (with the old `timeout` value) and start a new one (with the new `timeout` value). + +### onMount + +- Type: `boolean` +- Default: `false` + +Whether to immediately call the effect and trigger the debouncing mechanism when the hook is mounted. diff --git a/docs/hooks/use-debounce.md b/docs/hooks/use-debounce.md new file mode 100644 index 0000000..b923578 --- /dev/null +++ b/docs/hooks/use-debounce.md @@ -0,0 +1,46 @@ +# useDebounce + +Debounce a value. + +```ts +const debouncedValue = useDebounce(value, { timeout: 1000 }); +``` + +## Parameters + +### value + +- Type: `T` + +The value to be debounced. + +### options + +- Type: `UseDebounceOptions` +- Default: `{}` + +The options to configure the hook. + +## Options + +### timeout + +- Type: `number` +- Default: 500 + +The timeout in milliseconds between the last action of change and the actual time of that change being applied. + +Changes of this value will clear the current timer (with the old `timeout` value) and start a new one (with the new `timeout` value). + +### onMount + +- Type: `boolean` +- Default: `false` + +Whether to immediately start debouncing after the component is mounted. + +## Returns + +- Type: `T` + +The debounced value. diff --git a/src/use-async-effect.ts b/src/use-async-effect.ts index e8d6217..cd6015a 100644 --- a/src/use-async-effect.ts +++ b/src/use-async-effect.ts @@ -2,14 +2,24 @@ import { useEffect, type DependencyList, type EffectCallback } from "react"; import { useLatest } from "./use-latest"; /** - * Same as `EffectCallback`, but can return a promise. + * Same as `EffectCallback`, but can be asynchronous. */ export type AsyncEffectCallback = ( ...args: Parameters ) => Promise>; /** - * Same as `useEffect`, but can accept an async function. + * Same as `useEffect`, but the effect can be asynchronous. + * + * @param effect The asynchronous effect to run. + * @param deps The dependencies of the effect, just like in `useEffect`. + * Defaults to `undefined`. + * + * @note + * Destructor is not yet supported. The cleanup function returned by the + * effect will be ignored and discarded. + * + * @see https://hooks.mrcai.dev/hooks/use-async-effect */ export function useAsyncEffect( effect: AsyncEffectCallback, diff --git a/src/use-boolean.ts b/src/use-boolean.ts index d46b589..dee25cf 100644 --- a/src/use-boolean.ts +++ b/src/use-boolean.ts @@ -2,6 +2,13 @@ import { useState } from "react"; /** * Use a boolean value. + * + * @param initialValue The initial value of the boolean. + * + * @returns An object containing the current value of the boolean and functions + * to update it. + * + * @see https://hooks.mrcai.dev/hooks/use-boolean */ export function useBoolean(initialValue = false) { const [value, setValue] = useState(initialValue); @@ -11,5 +18,36 @@ export function useBoolean(initialValue = false) { const toggle = () => setValue((value) => !value); const reset = () => setValue(initialValue); - return { value, set: setValue, setTrue, setFalse, toggle, reset }; + return { + /** + * The current value of the boolean. + */ + value, + + /** + * Set the value to any boolean. + */ + set: setValue, + + /** + * Set the value to `true`. + */ + setTrue, + + /** + * Set the value to `false`. + */ + setFalse, + + /** + * Toggle the value, that is, to set the value to `true` if it is currently + * `false`, and to `false` if it is currently `true`. + */ + toggle, + + /** + * Reset the value to the initial value. + */ + reset, + }; } diff --git a/src/use-click-outside.ts b/src/use-click-outside.ts index 636943c..1b3d7aa 100644 --- a/src/use-click-outside.ts +++ b/src/use-click-outside.ts @@ -4,6 +4,13 @@ import { useLatest } from "./use-latest"; /** * Listen to click events outside of a node. + * + * @param ref The ref of the node to listen for click events outside of. + * @param callback The function to call when a click event occurs outside of + * the node. The first argument is the click event, and the second argument is + * the target node contained inside the `ref`. + * + * @see https://hooks.mrcai.dev/hooks/use-click-outside */ export function useClickOutside( ref: RefObject, diff --git a/src/use-clipboard-text.ts b/src/use-clipboard-text.ts index 3146d96..eda8da5 100644 --- a/src/use-clipboard-text.ts +++ b/src/use-clipboard-text.ts @@ -1,12 +1,33 @@ import { useEffect, useState } from "react"; import { useDocumentEventListener } from "./use-document-event-listener"; +/** + * The options to configure the `useClipboardText` hook. + */ export type UseClipboardTextOptions = { + /** + * Whether to immediately read the user's clipboard when the hook is mounted. + * + * If set to `false`, the returned `text` will be its default value, that is, + * `""`. + * + * When this option is changed from `false` to `true`, the hook will read the + * user's clipboard. + * + * @default true + */ readOnMount?: boolean; }; /** - * Use the text on user's clipboard. + * Use the text on the user's clipboard. + * + * @param options - The options to configure the hook. + * + * @returns An object containing the text on the user's clipboard, the error + * occurred, and a function to write text to the clipboard. + * + * @see https://hooks.mrcai.dev/hooks/use-clipboard-text */ export function useClipboardText(options: UseClipboardTextOptions = {}) { const { readOnMount = true } = options; @@ -60,5 +81,24 @@ export function useClipboardText(options: UseClipboardTextOptions = {}) { // TODO: Visibility change event listener - return { text, error, write }; + return { + /** + * The text on the user's clipboard. + */ + text, + + /** + * The error that occurs while reading from or writing to the user's + * clipboard. + * + * After any successful read or write operation, `error` will be reset to + * `null`. + */ + error, + + /** + * Write text to the user's clipboard. + */ + write, + }; } diff --git a/src/use-const-fn.ts b/src/use-const-fn.ts index a9070a4..f62da55 100644 --- a/src/use-const-fn.ts +++ b/src/use-const-fn.ts @@ -2,7 +2,13 @@ import { useCallback } from "react"; import type { Fn } from "./types"; /** - * Use an immutable function, which stays the same across re-renders. + * Memoize a function, which stays the same across rerenders. + * + * @param fn The function to memoize. + * + * @returns Exactly the same function. + * + * @see https://hooks.mrcai.dev/hooks/use-const-fn */ export function useConstFn(fn: T) { return useCallback(fn, []); diff --git a/src/use-const.ts b/src/use-const.ts index a132c3c..9e68abd 100644 --- a/src/use-const.ts +++ b/src/use-const.ts @@ -1,7 +1,9 @@ import { useMemo } from "react"; /** - * Use an immutable value, which stays the same across re-renders. + * Memoize a value, which stays the same across rerenders. + * + * @see https://hooks.mrcai.dev/hooks/use-const */ export function useConst(factory: () => T) { return useMemo(factory, []); diff --git a/src/use-counter.ts b/src/use-counter.ts index 06b3ecf..55c4203 100644 --- a/src/use-counter.ts +++ b/src/use-counter.ts @@ -2,6 +2,13 @@ import { useState } from "react"; /** * Use a counter. + * + * @param initialCount The initial value of the counter. + * + * @return An object containing the current value of the counter and functions + * to update it. + * + * @see https://hooks.mrcai.dev/hooks/use-counter */ export function useCounter(initialCount = 0) { const [count, setCount] = useState(initialCount); diff --git a/src/use-debounce-effect.ts b/src/use-debounce-effect.ts index 947351f..5457dab 100644 --- a/src/use-debounce-effect.ts +++ b/src/use-debounce-effect.ts @@ -6,13 +6,36 @@ import { } from "react"; import { useLatest } from "./use-latest"; +/** + * The options to configure `useDebounceEffect` hook. + */ export type UseDebounceEffectOptions = { + /** + * The time in milliseconds between the last call of the effect and the + * actual execution. + * + * Changes of this value will clear the current timer (with the old `timeout` + * value) and start a new one (with the new `timeout` value). + * + * @default 500 + */ timeout?: number; + + /** + * Whether to immediately call the effect and trigger the debouncing + * mechanism when the hook is mounted. + * + * @default false + */ onMount?: boolean; }; /** * Debounce an effect. + * + * @param effect The effect to be debounced. + * @param deps The dependencies of the effect, just like in `useEffect`. + * @param options The options to configure the hook. */ export function useDebounceEffect( effect: EffectCallback, diff --git a/src/use-debounce.ts b/src/use-debounce.ts index fdfbb1a..fe51018 100644 --- a/src/use-debounce.ts +++ b/src/use-debounce.ts @@ -1,13 +1,36 @@ import { useState } from "react"; import { useDebounceEffect } from "./use-debounce-effect"; +/** + * The options to configure the `useDebounce` hook. + */ export type UseDebounceOptions = { + /** + * The timeout in milliseconds between the last action of change and the + * actual time of that change being applied. + * + * Changes of this value will clear the current timer (with the old `timeout` + * value) and start a new one (with the new `timeout` value). + * + * @default 500 + */ timeout?: number; + + /** + * Whether to immediately start debouncing after the component is mounted. + * + * @default false + */ onMount?: boolean; }; /** * Debounce a value. + * + * @param value The value to be debounced. + * @param options The options to configure the hook. + * + * @returns The debounced value. */ export function useDebounce(value: T, options: UseDebounceOptions = {}) { const [debouncedValue, setDebouncedValue] = useState(value);