From 0592ea6ea5d748c508ad05a5e6c1734cdbab7e32 Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Fri, 19 Apr 2024 19:53:01 +0530 Subject: [PATCH 1/7] ci: add size-limit config in package.json --- .size-limit.json | 10 ---------- package.json | 12 +++++++++++- 2 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 .size-limit.json diff --git a/.size-limit.json b/.size-limit.json deleted file mode 100644 index b51964a..0000000 --- a/.size-limit.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "path": "dist/index.mjs", - "limit": "10 KB" - }, - { - "path": "dist/index.js", - "limit": "10 KB" - } -] diff --git a/package.json b/package.json index b45a4d6..f5098e8 100644 --- a/package.json +++ b/package.json @@ -80,5 +80,15 @@ "tabWidth": 3, "jsxSingleQuote": true, "trailingComma": "es5" - } + }, + "size-limit": [ + { + "path": "dist/index.mjs", + "limit": "10 KB" + }, + { + "path": "dist/index.js", + "limit": "10 KB" + } + ] } From 734ed24d1293c78c5252f1fbf6acf5e5ee316124 Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Sat, 20 Apr 2024 20:30:18 +0530 Subject: [PATCH 2/7] docs: refactor docs --- README.md | 2 +- apps/doc/hooks/use-debounced-fn.md | 2 +- apps/doc/hooks/use-interval-effect.md | 2 +- apps/doc/hooks/use-local-storage.md | 10 +++++----- apps/doc/hooks/use-on-mount-effect.md | 2 +- apps/doc/hooks/use-outside-click.md | 10 +++------- apps/doc/hooks/use-synced-effect.md | 2 +- apps/doc/hooks/use-timeout-effect.md | 2 +- 8 files changed, 14 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8e23c03..4c02fd9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 🚀 classic-react-hooks -#### A simple and minimal library of `custom react hooks`. +#### A simple and awesome collection of `custom react hooks`.
diff --git a/apps/doc/hooks/use-debounced-fn.md b/apps/doc/hooks/use-debounced-fn.md index 15f136f..878021d 100644 --- a/apps/doc/hooks/use-debounced-fn.md +++ b/apps/doc/hooks/use-debounced-fn.md @@ -15,7 +15,7 @@ outline: deep ### Returns -- It returns a function which debouced version of passed cb. +- It returns a function which is debouced version of passed callback. ### Usage diff --git a/apps/doc/hooks/use-interval-effect.md b/apps/doc/hooks/use-interval-effect.md index 0ed262f..d572d7a 100644 --- a/apps/doc/hooks/use-interval-effect.md +++ b/apps/doc/hooks/use-interval-effect.md @@ -4,7 +4,7 @@ outline: deep # use-interval-effect -- A hooks which fires the provided callback every time when the given delay is passed, just like the setInterval. +- A hooks which fires the provided callback every time when the given delay is passed, just like the `setInterval`. ### Parameters diff --git a/apps/doc/hooks/use-local-storage.md b/apps/doc/hooks/use-local-storage.md index 4d8e990..4af8e56 100644 --- a/apps/doc/hooks/use-local-storage.md +++ b/apps/doc/hooks/use-local-storage.md @@ -6,14 +6,14 @@ outline: deep - A hook for managing the states with `local-storage` - It automatically updates the state in `local-storage` -- `useState` with local storage power. +- It is `useState` with local storage power. ### Parameters -| Parameter | Type | Required | Default Value | Description | -| ------------ | :----: | :------: | :-----------: | ------------------------------------------------------ | -| key | string | ✅ | - | key for getting from local-storage | -| defaultValue | any | ❌ | - | A initial value when item is not present local-storage | +| Parameter | Type | Required | Default Value | Description | +| ------------ | :----: | :------: | :-----------: | ---------------------------------------------------- | +| key | string | ✅ | - | key for getting an item from local-storage | +| defaultValue | any | ❌ | - | A initial value when item is not found local-storage | ### Returns diff --git a/apps/doc/hooks/use-on-mount-effect.md b/apps/doc/hooks/use-on-mount-effect.md index da63e9b..c96d4ea 100644 --- a/apps/doc/hooks/use-on-mount-effect.md +++ b/apps/doc/hooks/use-on-mount-effect.md @@ -11,7 +11,7 @@ outline: deep | Parameter | Type | Required | Default Value | Description | | --------- | :------: | :------: | :-----------: | ------------------------------------- | -| cb | Function | ✅ | - | Function to fire after initial mount. | +| cb | Function | ✅ | - | Callback to fire after initial mount. | ### Usage diff --git a/apps/doc/hooks/use-outside-click.md b/apps/doc/hooks/use-outside-click.md index cbeefde..8873382 100644 --- a/apps/doc/hooks/use-outside-click.md +++ b/apps/doc/hooks/use-outside-click.md @@ -33,13 +33,9 @@ import { useOutsideClick } from 'classic-react-hooks' export default function YourComponent() { const modalRef = useRef(null) - useOutsideClick( - () => modalRef.current, - (e) => { - console.log('clicked outside on modal. Target = ', e.target) - }, - true - ) + useOutsideClick(modalRef, (e) => { + console.log('clicked outside on modal. Target = ', e.target) + }) return (
diff --git a/apps/doc/hooks/use-synced-effect.md b/apps/doc/hooks/use-synced-effect.md index 9d4c8b6..9d2402c 100644 --- a/apps/doc/hooks/use-synced-effect.md +++ b/apps/doc/hooks/use-synced-effect.md @@ -11,7 +11,7 @@ outline: deep | Parameter | Type | Required | Default Value | Description | | --------- | :------: | :------: | :-----------: | ----------------------------------------------- | -| cb | Function | ✅ | - | Function to fire when dependencies get changed. | +| cb | Function | ✅ | - | Callback to fire when dependencies get changed. | | deps | Array | ❌ | [] | Dependencies. | ### Usage diff --git a/apps/doc/hooks/use-timeout-effect.md b/apps/doc/hooks/use-timeout-effect.md index 8c8acfe..2e19336 100644 --- a/apps/doc/hooks/use-timeout-effect.md +++ b/apps/doc/hooks/use-timeout-effect.md @@ -4,7 +4,7 @@ outline: deep # use-timeout-effect -- A hooks which fires the provided callback only once when the given delay is passed, just like the setTimeout. +- A hooks which fires the provided callback only once when the given delay is passed, just like the `setTimeout`. ### Parameters From 71c948a1235ffe125a0114d7d05c36f7769d0696 Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Sun, 21 Apr 2024 19:44:38 +0530 Subject: [PATCH 3/7] feat: add ref support as target in use-outside-click hook with test cases --- src/lib/use-outside-click/index.test.tsx | 22 ++++++++++++++++++++++ src/lib/use-outside-click/index.tsx | 12 ++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/lib/use-outside-click/index.test.tsx b/src/lib/use-outside-click/index.test.tsx index c824dd4..a6ab3ad 100644 --- a/src/lib/use-outside-click/index.test.tsx +++ b/src/lib/use-outside-click/index.test.tsx @@ -30,6 +30,28 @@ describe('use-outside-click', () => { expect(addSpy).toHaveBeenCalledTimes(1) expect(removeSpy).toHaveBeenCalledTimes(1) }) + it('should work with refs', () => { + const div = document.createElement('div') + const addSpy = vi.spyOn(document, 'addEventListener') + const removeSpy = vi.spyOn(document, 'removeEventListener') + + const ref = { current: div } + + const { rerender, unmount } = renderHook(() => { + useOutsideClick(ref, () => {}) + }) + + expect(addSpy).toHaveBeenCalledTimes(1) + expect(removeSpy).toHaveBeenCalledTimes(0) + + rerender() + expect(addSpy).toHaveBeenCalledTimes(1) + expect(removeSpy).toHaveBeenCalledTimes(0) + + unmount() + expect(addSpy).toHaveBeenCalledTimes(1) + expect(removeSpy).toHaveBeenCalledTimes(1) + }) it('should fire listener when clicked outside of target element', () => { const div = document.createElement('div') diff --git a/src/lib/use-outside-click/index.tsx b/src/lib/use-outside-click/index.tsx index 9af9787..b1cdd5d 100644 --- a/src/lib/use-outside-click/index.tsx +++ b/src/lib/use-outside-click/index.tsx @@ -1,9 +1,9 @@ 'use client' -import React, { useCallback } from 'react' +import React, { RefObject, useCallback } from 'react' import { useEventListener } from '../use-event-listener' import useSyncedRef from '../use-synced-ref' -type Target = null | EventTarget | (() => EventTarget | null) +type Target = null | EventTarget | RefObject | (() => EventTarget | null) /** * @description @@ -41,9 +41,13 @@ export default function useOutsideClick( const eventCb = useCallback((event: DocumentEventMap['click']) => { const node = (typeof target == 'function' ? target() : target) ?? document - if (event.target == node) return + if (event.target == node || ('current' in node && event.target == node.current)) return - if (node && (node as Node).contains(event.target as Node)) { + if ( + node && + ((node as Node).contains(event.target as Node) || + ('current' in node && (node.current as Node).contains(event.target as Node))) + ) { return } paramsRef.current.handler(event) From 5f73180dab244c8480f460e852cda46fe481f2dc Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Sun, 21 Apr 2024 19:45:59 +0530 Subject: [PATCH 4/7] feat: handle edge case for use-synced-effect double time firing in React strict mode --- src/lib/use-synced-effect/index.test.tsx | 17 ++++++++++++----- src/lib/use-synced-effect/index.tsx | 13 +++++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/lib/use-synced-effect/index.test.tsx b/src/lib/use-synced-effect/index.test.tsx index bf8e42a..06492fb 100644 --- a/src/lib/use-synced-effect/index.test.tsx +++ b/src/lib/use-synced-effect/index.test.tsx @@ -3,6 +3,10 @@ import { vi } from 'vitest' import useSyncedEffect from '.' describe('use-on-mount-effect', () => { + beforeEach(() => { + vi.useFakeTimers() + }) + it('should not run callback on initial the mount', () => { const fn = vi.fn() renderHook(() => useSyncedEffect(fn, [])) @@ -18,15 +22,17 @@ describe('use-on-mount-effect', () => { const fn = vi.fn() let skill = 'js' - const { rerender } = renderHook((props: Array) => useSyncedEffect(fn, props ?? [skill])) + const { rerender } = renderHook(() => useSyncedEffect(fn, [skill])) expect(fn).toHaveBeenCalledTimes(0) + vi.runAllTimers() + skill = 'react' - rerender([skill]) + rerender() expect(fn).toHaveBeenCalledTimes(1) skill = 'typescript' - rerender([skill]) + rerender() expect(fn).toHaveBeenCalledTimes(2) }) @@ -35,10 +41,11 @@ describe('use-on-mount-effect', () => { const fn = vi.fn(() => cleanupFn) let skill = 'js' - const { rerender, unmount } = renderHook((props: Array) => useSyncedEffect(fn, props ?? [skill])) + const { rerender, unmount } = renderHook(() => useSyncedEffect(fn, [skill])) + vi.runAllTimers() skill = 'react' - rerender([skill]) + rerender() expect(fn).toHaveBeenCalledTimes(1) unmount() diff --git a/src/lib/use-synced-effect/index.tsx b/src/lib/use-synced-effect/index.tsx index 3422696..d743a53 100644 --- a/src/lib/use-synced-effect/index.tsx +++ b/src/lib/use-synced-effect/index.tsx @@ -36,11 +36,20 @@ export default function useSyncedEffect(cb: EffectCallback, deps?: DependencyLis const cleanup = useRef void)>() useEffect(() => { + let timeoutId: NodeJS.Timeout if (isInitialLoad.current) { - isInitialLoad.current = false + // handling React.StrictMode double time firing + timeoutId = setTimeout(() => { + isInitialLoad.current = false + }) } else { cleanup.current = cb() } - return cleanup.current + return () => { + if (timeoutId) { + clearTimeout(timeoutId) + } + cleanup.current?.() + } }, deps ?? DEP) } From ba41ac08bc98c2c93a3cc889fd30e7b66c7b7527 Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Sun, 21 Apr 2024 19:46:44 +0530 Subject: [PATCH 5/7] fix: update delay from 0 to 100 in use-timeout-effect hook --- src/lib/use-timeout-effect/index.test.tsx | 2 +- src/lib/use-timeout-effect/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/use-timeout-effect/index.test.tsx b/src/lib/use-timeout-effect/index.test.tsx index 0267203..131c56a 100644 --- a/src/lib/use-timeout-effect/index.test.tsx +++ b/src/lib/use-timeout-effect/index.test.tsx @@ -18,7 +18,7 @@ describe('use-timeout-effect', () => { renderHook(() => useTimoeoutEffect(fn)) expect(fn).toHaveBeenCalledTimes(0) - vi.advanceTimersByTime(0) + vi.advanceTimersByTime(100) expect(fn).toHaveBeenCalledTimes(1) }) diff --git a/src/lib/use-timeout-effect/index.tsx b/src/lib/use-timeout-effect/index.tsx index d67131d..0d4088b 100644 --- a/src/lib/use-timeout-effect/index.tsx +++ b/src/lib/use-timeout-effect/index.tsx @@ -27,7 +27,7 @@ import useSyncedRef from '../use-synced-ref' ) } */ -export default function useTimeoutEffect(cb: () => void, timeout = 0) { +export default function useTimeoutEffect(cb: () => void, timeout = 100) { let paramsRef = useSyncedRef({ cb, timeout, From c6ca9c0c190faf642e668fb3bd9f8e49facbf248 Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Sun, 21 Apr 2024 19:46:58 +0530 Subject: [PATCH 6/7] style: update prettierignore config --- .prettierignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.prettierignore b/.prettierignore index 5b2eaaa..c7cc023 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,4 +2,5 @@ dist coverage node_modules public -apps/doc/.vitepress/cache \ No newline at end of file +apps/doc/.vitepress/cache +.changeset \ No newline at end of file From 34866b5d12418ffd5f7d0f80b4320a15fd92e41f Mon Sep 17 00:00:00 2001 From: ashish-simpleCoder Date: Mon, 22 Apr 2024 15:05:42 +0530 Subject: [PATCH 7/7] docs: add contribution guide line --- CONTRIBUTING.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 4 ++++ 2 files changed, 52 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..fcff9ca --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contributing Guide + +Hi! We are really excited that you are interested in contributing to classic-react-hooks. Before submitting your contribution, please make sure to take a moment and read through the following guide: + +## Repo Setup + +The package manager used to install and link dependencies must be [pnpm](https://pnpm.io/). NodeJS version should be v18.14.2 or higher + +1. Run `pnpm install` in root folder + +2. Run `pnpm run build` to build the package + +3. Run `pnpm run test` to run the test cases + +4. Run `pnpm run format` to format all of the coding with prettier + +## Pull Request Guidelines + +- Checkout a topic branch from a base branch, e.g. `main`, and merge back against that branch. + +- If adding a new feature: + + - Add accompanying test case. + - Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it. + +- If fixing bug: + + - If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `fix: update entities encoding/decoding (fix #3899)`. + - Provide a detailed description of the bug in the PR. Live demo preferred. + - Add appropriate test coverage if applicable. + +- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging. + +- Make sure tests pass! + +- Use `pnpm format` to format files according to the project guidelines. + +## Documenation Guidelines + +- To make contribute in the documentation, go to apps/doc directory + +1. Run `pnpm install` to install all of the dependencies + +2. Run `pnpm docs:dev` for development of doc + +3. Run `pnpm docs:build` for building the prodution version of doc + +4. Run `pnpm docs:preview` to see the preview of doc diff --git a/README.md b/README.md index 4c02fd9..4061b73 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,7 @@ $ yarn add classic-react-hooks - use-synced-effect - use-on-mount-effect - use-counter + +## Contribution + +See [Contributing Guide](https://github.com/Ashish-simpleCoder/classic-react-hooks/blob/main/CONTRIBUTING.md).