diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1dd2e5f6bd..c4d761627e 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,17 +3,25 @@ version: 2
refs:
container: &container
docker:
- - image: node:12.12.0
+ - image: node:12.14.0
working_directory: ~/repo
steps:
- &Versions
run:
name: Versions
command: node -v && npm -v && yarn -v
+ - &CacheRestore
+ restore_cache:
+ key: dependency-cache-{{ checksum "yarn.lock" }}
- &Install
run:
name: Install Dependencies
command: yarn install --pure-lockfile
+ - &CacheSave
+ save_cache:
+ key: dependency-cache-{{ checksum "yarn.lock" }}
+ paths:
+ - ./node_modules
- &Build
run:
name: Build
@@ -42,8 +50,9 @@ refs:
run:
name: Post commit status for Storybook
command: |
- npx cross-ci :run \
- npx commit-status success Storybook "'\${BUILD_VERSION}'" "'https://$CIRCLE_BUILD_NUM-154950925-gh.circle-artifacts.com/0/root/repo/storybook-static/index.html'"
+ npx cross-ci :run curl -H "'Authorization: token \${GITHUB_TOKEN}' -H 'Accept: application/vnd.github.v3+json'" \
+ "'https://api.github.com/repos/\${PROJECT_OWNER}/\${PROJECT_NAME}/statuses/$CIRCLE_SHA1'" -X POST \
+ -d "'{\"state\": \"success\", \"context\": \"Storybook\", \"description\": \"\${BUILD_VERSION}\", \"target_url\": \"https://$CIRCLE_BUILD_NUM-154950925-gh.circle-artifacts.com/0/root/repo/storybook-static/index.html\"}'"
jobs:
all:
@@ -51,7 +60,9 @@ jobs:
steps:
- checkout
- *Versions
+ - *CacheRestore
- *Install
+ - *CacheSave
- *Build
- *Build_Storybook
- *Test
@@ -65,7 +76,9 @@ jobs:
steps:
- checkout
- *Versions
+ - *CacheRestore
- *Install
+ - *CacheSave
- *Build
- *Build_Storybook
- *Test
@@ -87,7 +100,9 @@ jobs:
steps:
- checkout
- *Versions
+ - *CacheRestore
- *Install
+ - *CacheSave
- *Build
- *Build_Storybook
- *Test
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..bfcd240e6f
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,25 @@
+# Description
+
+
+
+
+## Type of change
+
+
+- [ ] Bug fix _(non-breaking change which fixes an issue)_
+- [ ] New feature _(non-breaking change which adds functionality)_
+- [ ] **Breaking change** _(fix or feature that would cause existing functionality to not work as before)_
+
+# Checklist
+- [ ] Read the [Contributing Guide](https://github.com/streamich/react-use/blob/master/CONTRIBUTING.md)
+- [ ] Perform a code self-review
+- [ ] Comment the code, particularly in hard-to-understand areas
+- [ ] Add documentation
+- [ ] Add hook's story at Storybook
+- [ ] Cover changes with tests
+- [ ] Ensure the test suite passes (`yarn test`)
+- [ ] Provide 100% tests coverage
+- [ ] Make sure code lints (`yarn lint`). Fix it with `yarn lint:fix` in case of failure.
+- [ ] Make sure types are fine (`yarn lint:types`).
+
+
diff --git a/.storybook/config.js b/.storybook/config.js
index 9300b1e920..93dcc97cfc 100644
--- a/.storybook/config.js
+++ b/.storybook/config.js
@@ -12,7 +12,7 @@ setOptions({
sidebarAnimations: false,
});
-const req = require.context('../src/', true, /.*\.(stories|story)\.(js|jsx|ts|tsx)?$/);
+const req = require.context('../stories/', true, /\.story\.tsx?$/);
const loadStories = () => {
req.keys().forEach((filename) => req(filename));
diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js
index f3eef02591..5771154606 100644
--- a/.storybook/webpack.config.js
+++ b/.storybook/webpack.config.js
@@ -1,35 +1,39 @@
const path = require('path');
-const {compilerOptions} = require('../tsconfig.json');
+const { compilerOptions } = require('../tsconfig.json');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
-const SRC_PATH = path.join(__dirname, '../src');
+const basedir = path.join(__dirname, '..');
-module.exports = {
- module: {
- rules: [
- {
- test: /\.md?$/,
- loader: "markdown-loader",
- },
- {
- test: /\.tsx?$/,
- loader: 'ts-loader',
- include: [
- SRC_PATH,
- ],
- options: {
- transpileOnly: true, // use transpileOnly mode to speed-up compilation
- compilerOptions: {
- ...compilerOptions,
- declaration: false,
- },
+module.exports = async ({ config, mode }) => {
+ config.module.rules.push(
+ {
+ test: /\.md?$/,
+ loader: "markdown-loader",
+ },
+ {
+ test: /\.tsx?$/,
+ loader: 'ts-loader',
+ include: [
+ path.join(basedir, 'src'),
+ path.join(basedir, 'stories'),
+ ],
+ options: {
+ transpileOnly: true, // use transpileOnly mode to speed-up compilation
+ compilerOptions: {
+ ...compilerOptions,
+ declaration: false,
},
- }
- ]
- },
- resolve: {
- extensions: ['.ts', '.tsx', '.js', '.jsx'],
- enforceExtension: false
- },
- plugins: [new ForkTsCheckerWebpackPlugin()],
+ },
+ },
+ );
+
+ config.plugins.push(new ForkTsCheckerWebpackPlugin());
+
+ config.resolve.extensions = ['.ts', '.tsx', '.js', '.jsx'];
+ config.resolve.enforceExtension = false;
+
+ // disable the hint about too big bundle
+ config.performance.hints = false;
+
+ return config;
};
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78784e127d..fa8894c99e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,288 @@
+# [13.13.0](https://github.com/streamich/react-use/compare/v13.12.2...v13.13.0) (2019-12-27)
+
+
+### Features
+
+* add useShallowCompareEffect and useCustomCompareEffect hooks ([ba8803e](https://github.com/streamich/react-use/commit/ba8803eab26d2d48028a4b7120a7354c6d318aea))
+
+## [13.12.2](https://github.com/streamich/react-use/compare/v13.12.1...v13.12.2) (2019-12-10)
+
+
+### Bug Fixes
+
+* **useSet:** "has" method in useSet updated to reference latest set object ([4f1d8c2](https://github.com/streamich/react-use/commit/4f1d8c2cbd773f2a26e2eee4fbad88883ea4b405))
+
+## [13.12.1](https://github.com/streamich/react-use/compare/v13.12.0...v13.12.1) (2019-12-09)
+
+
+### Bug Fixes
+
+* **useMap:** methods with side effects should be stable across renders. ([020b4db](https://github.com/streamich/react-use/commit/020b4dbc6c47ab25243ab8af257dd045e6c1bf6d))
+
+# [13.12.0](https://github.com/streamich/react-use/compare/v13.11.0...v13.12.0) (2019-12-09)
+
+
+### Features
+
+* useScrollbarWidth hook; ([#825](https://github.com/streamich/react-use/issues/825)) ([125c7e9](https://github.com/streamich/react-use/commit/125c7e96a188405aea36e94ed1bb3d984232b2f6))
+
+# [13.11.0](https://github.com/streamich/react-use/compare/v13.10.2...v13.11.0) (2019-12-08)
+
+
+### Features
+
+* 🎸 add useUnmountPromise hook ([01421bc](https://github.com/streamich/react-use/commit/01421bc634b941044e95c611f37eb87339486241))
+
+## [13.10.2](https://github.com/streamich/react-use/compare/v13.10.1...v13.10.2) (2019-12-05)
+
+
+### Bug Fixes
+
+* useUpdate hitting maxInt, failing to trigger rerender ([93e7291](https://github.com/streamich/react-use/commit/93e72910abf2dafe5bdff625a21f633afd6e52c5))
+
+## [13.10.1](https://github.com/streamich/react-use/compare/v13.10.0...v13.10.1) (2019-12-03)
+
+
+### Bug Fixes
+
+* "get" method in useMap updated to reference latest map object ([044d267](https://github.com/streamich/react-use/commit/044d2677aa474d19da776444b78bd3d2594c6ae5))
+
+# [13.10.0](https://github.com/streamich/react-use/compare/v13.9.0...v13.10.0) (2019-11-28)
+
+
+### Features
+
+* useStateHistory ([#709](https://github.com/streamich/react-use/issues/709)) ([0a66359](https://github.com/streamich/react-use/commit/0a6635914319e9ef7a2902189a3c2dea90a2bf7f))
+
+# [13.9.0](https://github.com/streamich/react-use/compare/v13.8.2...v13.9.0) (2019-11-23)
+
+
+### Features
+
+* add useFirstMountState & useRendersCount hooks ([#769](https://github.com/streamich/react-use/issues/769)) ([30abe2b](https://github.com/streamich/react-use/commit/30abe2b22e3cb7a3e4c6dedd2466d74ce660911d))
+
+## [13.8.2](https://github.com/streamich/react-use/compare/v13.8.1...v13.8.2) (2019-11-22)
+
+
+### Bug Fixes
+
+* **#792:** make useUnmount invoke the current callback version instead of very first ([75284c6](https://github.com/streamich/react-use/commit/75284c62c8e4a68dfeb41a8d98a1e636e9ef531a)), closes [#792](https://github.com/streamich/react-use/issues/792)
+
+## [13.8.1](https://github.com/streamich/react-use/compare/v13.8.0...v13.8.1) (2019-11-21)
+
+
+### Bug Fixes
+
+* useAsyncFn does not discard old promises and might produce races ([022fa0b](https://github.com/streamich/react-use/commit/022fa0b7b77d582a10c6ca61a3dcd901770011c8))
+
+# [13.8.0](https://github.com/streamich/react-use/compare/v13.7.0...v13.8.0) (2019-11-14)
+
+
+### Features
+
+* **useStateValidator:** Refactor method and improve typings; ([436c210](https://github.com/streamich/react-use/commit/436c210f7b577c6958e47df3a244907b07a4db9f))
+
+# [13.7.0](https://github.com/streamich/react-use/compare/v13.6.3...v13.7.0) (2019-11-14)
+
+
+### Features
+
+* Add useSet hook ([095b4de](https://github.com/streamich/react-use/commit/095b4de2321b8bf3431e3f66139629b0495f1ac9))
+
+## [13.6.3](https://github.com/streamich/react-use/compare/v13.6.2...v13.6.3) (2019-11-12)
+
+
+### Bug Fixes
+
+* remove any types in useThrottleFn ([bb5baea](https://github.com/streamich/react-use/commit/bb5baea30cf59721098ca9e3185105bf1b82218b))
+
+## [13.6.2](https://github.com/streamich/react-use/compare/v13.6.1...v13.6.2) (2019-11-11)
+
+
+### Bug Fixes
+
+* restrict useThrottleFn types ([61a83d1](https://github.com/streamich/react-use/commit/61a83d124d35d5606b6c0700faf1361fd3170ca4))
+
+## [13.6.1](https://github.com/streamich/react-use/compare/v13.6.0...v13.6.1) (2019-11-10)
+
+
+### Bug Fixes
+
+* 🐛 check window.Event constructor exists in useLocation ([ad09431](https://github.com/streamich/react-use/commit/ad094311454c48873ba7143654a29b8a0c54459d))
+
+# [13.6.0](https://github.com/streamich/react-use/compare/v13.5.0...v13.6.0) (2019-11-10)
+
+
+### Features
+
+* **useCounter:** `reset` to the newest initialValue ([#667](https://github.com/streamich/react-use/issues/667)) ([e653383](https://github.com/streamich/react-use/commit/e65338372adfccd4800496b377f63bcdf6646788))
+
+# [13.5.0](https://github.com/streamich/react-use/compare/v13.4.0...v13.5.0) (2019-11-08)
+
+
+### Bug Fixes
+
+* **resolveHookState:** by accident removed needed type. ([59aa41c](https://github.com/streamich/react-use/commit/59aa41cff435f5adf7f38d361649761b8dd69794))
+
+
+### Features
+
+* **useList:** reimplemented useList hook; ([1840b57](https://github.com/streamich/react-use/commit/1840b577e2a3d321b8dbb44d5ae443e84d4d9e20))
+
+# [13.4.0](https://github.com/streamich/react-use/compare/v13.3.0...v13.4.0) (2019-11-08)
+
+
+### Features
+
+* **useStateList:** implemented `currentIndex`, `setState`, `setStateAt` methods as requested in [#634](https://github.com/streamich/react-use/issues/634); ([43cb6aa](https://github.com/streamich/react-use/commit/43cb6aa612ae869e24f67acf6f0a1712a65f128b))
+
+# [13.3.0](https://github.com/streamich/react-use/compare/v13.2.2...v13.3.0) (2019-11-06)
+
+
+### Features
+
+* useDebounce add cancel ([693aec8](https://github.com/streamich/react-use/commit/693aec8307c378697c88c635a401832f24d3531a))
+* useDebounce add cancel ([26cab31](https://github.com/streamich/react-use/commit/26cab31f10a995ec45d6c1e2a2f724d9994d801f))
+
+## [13.2.2](https://github.com/streamich/react-use/compare/v13.2.1...v13.2.2) (2019-11-06)
+
+
+### Bug Fixes
+
+* **#749:** now should work with SSR ([c12976c](https://github.com/streamich/react-use/commit/c12976cad26577a4be3ac65133268f41bbdc82da)), closes [#749](https://github.com/streamich/react-use/issues/749)
+
+## [13.2.1](https://github.com/streamich/react-use/compare/v13.2.0...v13.2.1) (2019-11-04)
+
+
+### Bug Fixes
+
+* **yarn.lock:** re-create the yarn.lock file with nailed versions in devDeps ([f094a3a](https://github.com/streamich/react-use/commit/f094a3ae833f406137b9d5355843a6615af20164))
+
+# [13.2.0](https://github.com/streamich/react-use/compare/v13.1.0...v13.2.0) (2019-11-04)
+
+
+### Features
+
+* re-create yarn.lock ([d48e03e](https://github.com/streamich/react-use/commit/d48e03e9ee38555ff29ca46fb6e75c13e9c23aba))
+* re-create yarn.lock ([ccdffe0](https://github.com/streamich/react-use/commit/ccdffe027fba15bdca1f35dc375a0c32739aee6f))
+* **usePreviousDistinct:** add tests for undefined value behaviour; ([cb373f9](https://github.com/streamich/react-use/commit/cb373f951fb3f34b9e54793687de14000a2dc08e))
+* **usePreviousDistinct:** improve types; ([30f53e8](https://github.com/streamich/react-use/commit/30f53e8c5d7e8b27bf3f273ebfcacabf30146ba3))
+* **usePreviousDistinct:** now predicate not called on initial render; ([fbe9b13](https://github.com/streamich/react-use/commit/fbe9b1303c0433d5608ca5b507d9c76711b5cb68))
+* **useStateList:** rework useStateList to make it work properly. ([242c274](https://github.com/streamich/react-use/commit/242c274dd49779fa80f8b9e451c699205279339e))
+* **useTitle:** reworked hook to make it synchronous without useUpdate; ([a133267](https://github.com/streamich/react-use/commit/a13326779ffd6885ac531240b984a77bcad3bee6))
+* **useWindowSize:** A bit changed lyfecycle and added types; ([03bdecf](https://github.com/streamich/react-use/commit/03bdecf7ac6aa0ad863a1efd71c056aa41df62b7))
+
+# [13.1.0](https://github.com/streamich/react-use/compare/v13.0.1...v13.1.0) (2019-11-01)
+
+
+### Features
+
+* pull request template for features ([1dc21f3](https://github.com/streamich/react-use/commit/1dc21f3))
+
+## [13.0.1](https://github.com/streamich/react-use/compare/v13.0.0...v13.0.1) (2019-11-01)
+
+
+### Bug Fixes
+
+* **useLockBodyScroll:** infer overflow type directly from declaration. ([26baf47](https://github.com/streamich/react-use/commit/26baf47))
+
+# [13.0.0](https://github.com/streamich/react-use/compare/v12.13.0...v13.0.0) (2019-11-01)
+
+
+* Merge pull request #711 from streamich/remove-react-wait ([8d40f18](https://github.com/streamich/react-use/commit/8d40f18)), closes [#711](https://github.com/streamich/react-use/issues/711)
+
+
+### Features
+
+* remove useRefMounted hook ([ad74d3d](https://github.com/streamich/react-use/commit/ad74d3d))
+* **useRefMounted:** remove obsolete hook; ([dc364c8](https://github.com/streamich/react-use/commit/dc364c8))
+* **useWait:** removed from package due to it is simple reexport of other package; ([d7c38bd](https://github.com/streamich/react-use/commit/d7c38bd))
+
+
+### BREAKING CHANGES
+
+* useWait hook has been removed from react-use
+* deprecated useRefMounted hook is now removed, use useMountedState hook instead
+
+# [12.13.0](https://github.com/streamich/react-use/compare/v12.12.0...v12.13.0) (2019-10-31)
+
+
+### Features
+
+* **useCounter:** reworked with use of new resolveHookState function plus improved memory usage; ([befcf84](https://github.com/streamich/react-use/commit/befcf84))
+* **useGetSet:** reworked with use of new resolveHookState function plus improved memory usage; ([9b5d0f2](https://github.com/streamich/react-use/commit/9b5d0f2))
+* react-like state resolver to use it in stateful hooks; ([9fd02eb](https://github.com/streamich/react-use/commit/9fd02eb))
+
+# [12.12.0](https://github.com/streamich/react-use/compare/v12.11.0...v12.12.0) (2019-10-31)
+
+
+### Features
+
+* add typings for createReducer ([f1cf036](https://github.com/streamich/react-use/commit/f1cf036))
+
+# [12.11.0](https://github.com/streamich/react-use/compare/v12.10.0...v12.11.0) (2019-10-31)
+
+
+### Features
+
+* **useWait:** add deprecation messages to readme and export; ([d338245](https://github.com/streamich/react-use/commit/d338245))
+
+# [12.10.0](https://github.com/streamich/react-use/compare/v12.9.1...v12.10.0) (2019-10-30)
+
+
+### Features
+
+* **useUpdate:** improve memory usage - now single function instance to increment all counters; ([0f02fd0](https://github.com/streamich/react-use/commit/0f02fd0))
+
+## [12.9.1](https://github.com/streamich/react-use/compare/v12.9.0...v12.9.1) (2019-10-28)
+
+
+### Bug Fixes
+
+* useSize avoid crash in Safari 11 ([da0e66b](https://github.com/streamich/react-use/commit/da0e66b))
+
+# [12.9.0](https://github.com/streamich/react-use/compare/v12.8.0...v12.9.0) (2019-10-26)
+
+
+### Features
+
+* add createBreakpoint ([79ba4ef](https://github.com/streamich/react-use/commit/79ba4ef))
+
+# [12.8.0](https://github.com/streamich/react-use/compare/v12.7.2...v12.8.0) (2019-10-25)
+
+
+### Features
+
+* add ensuredForwardRef and useEnsuredForwardedRef ([1bfe063](https://github.com/streamich/react-use/commit/1bfe063))
+
+## [12.7.2](https://github.com/streamich/react-use/compare/v12.7.1...v12.7.2) (2019-10-23)
+
+
+### Bug Fixes
+
+* 🐛 bump set-harmonic-interval package version ([f7c709a](https://github.com/streamich/react-use/commit/f7c709a))
+
+## [12.7.1](https://github.com/streamich/react-use/compare/v12.7.0...v12.7.1) (2019-10-17)
+
+
+### Bug Fixes
+
+* example in the docs; ([7f54cad](https://github.com/streamich/react-use/commit/7f54cad))
+* rename story's mediator and add `g` flag to it's regex; ([652b318](https://github.com/streamich/react-use/commit/652b318))
+
+# [12.7.0](https://github.com/streamich/react-use/compare/v12.6.0...v12.7.0) (2019-10-17)
+
+
+### Bug Fixes
+
+* error throw tests; ([056875b](https://github.com/streamich/react-use/commit/056875b))
+* useMultiStateValidator readme description; ([8c7f7f5](https://github.com/streamich/react-use/commit/8c7f7f5))
+
+
+### Features
+
+* useMultiStateValidator ([ae26988](https://github.com/streamich/react-use/commit/ae26988))
+
# [12.6.0](https://github.com/streamich/react-use/compare/v12.5.0...v12.6.0) (2019-10-16)
diff --git a/README.md b/README.md
index 712a092db4..64858f9f44 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,6 @@
-
Collection of essential React Hooks.
Port oflibreact.
@@ -66,6 +65,8 @@
- [`useWindowScroll`](./docs/useWindowScroll.md) — tracks `Window` scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usewindowscroll--docs)
- [`useWindowSize`](./docs/useWindowSize.md) — tracks `Window` dimensions. [![][img-demo]](https://codesandbox.io/s/m7ln22668)
- [`useMeasure`](./docs/useMeasure.md) — tracks an HTML element's dimensions using the Resize Observer API.[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo)
+ - [`createBreakpoint`](./docs/createBreakpoint.md) — tracks `innerWidth`
+ - [`useScrollbarWidth`](./docs/useScrollbarWidth.md) — detects browser's native scrollbars width. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usescrollbarwidth--demo)
- [**UI**](./docs/UI.md)
@@ -76,8 +77,8 @@
- [`useFullscreen`](./docs/useFullscreen.md) — display an element or video full-screen. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usefullscreen--demo)
- [`useSlider`](./docs/useSlider.md) — provides slide behavior over any HTML element. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-useslider--demo)
- [`useSpeech`](./docs/useSpeech.md) — synthesizes speech from a text string. [![][img-demo]](https://codesandbox.io/s/n090mqz69m)
+ - [`useVibrate`](./docs/useVibrate.md) — provide physical feedback using the [Vibration API](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API). [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usevibrate--demo)
- [`useVideo`](./docs/useVideo.md) — plays video, tracks its state, and exposes playback controls. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/ui-usevideo--demo)
- - [`useWait`](./docs/useWait.md) — complex waiting management for UIs.
- [**Side-effects**](./docs/Side-effects.md)
- - [`useAsync`](./docs/useAsync.md) — resolves an `async` function.
- - [`useAsyncFn`](./docs/useAsyncFn.md) — state management for an async function
- - [`useAsyncRetry`](./docs/useAsyncRetry.md) — `useAsync` with `retry()` method.
+ - [`useAsync`](./docs/useAsync.md), [`useAsyncFn`](./docs/useAsyncFn.md), and [`useAsyncRetry`](./docs/useAsyncRetry.md) — resolves an `async` function.
- [`useBeforeUnload`](./docs/useBeforeUnload.md) — shows browser alert when user try to reload or close the page.
- [`useCopyToClipboard`](./docs/useCopyToClipboard.md) — copies text to clipboard.
- [`useDebounce`](./docs/useDebounce.md) — debounces a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usedebounce--demo)
@@ -111,14 +110,14 @@
- [`useEffectOnce`](./docs/useEffectOnce.md) — a modified [`useEffect`](https://reactjs.org/docs/hooks-reference.html#useeffect) hook that only runs once.
- [`useEvent`](./docs/useEvent.md) — subscribe to events.
- [`useLifecycles`](./docs/useLifecycles.md) — calls `mount` and `unmount` callbacks.
- - [`useMountedState`](./docs/useMountedState.md) and [`useRefMounted`](./docs/useRefMounted.md) — track if component is mounted.
+ - [`useMountedState`](./docs/useMountedState.md) and [`useUnmountPromise`](./docs/useUnmountPromise.md) — track if component is mounted.
- [`usePromise`](./docs/usePromise.md) — resolves promise only while component is mounted.
- [`useLogger`](./docs/useLogger.md) — logs in console as component goes through life-cycles.
- [`useMount`](./docs/useMount.md) — calls `mount` callbacks.
- [`useUnmount`](./docs/useUnmount.md) — calls `unmount` callbacks.
- [`useUpdateEffect`](./docs/useUpdateEffect.md) — run an `effect` only on updates.
- [`useIsomorphicLayoutEffect`](./docs/useIsomorphicLayoutEffect.md) — `useLayoutEffect` that does not show warning when server-side rendering.
- - [`useDeepCompareEffect`](./docs/useDeepCompareEffect.md) — run an `effect` depending on deep comparison of its dependencies
+ - [`useDeepCompareEffect`](./docs/useDeepCompareEffect.md), [`useShallowCompareEffect`](./docs/useShallowCompareEffect.md), and [`useCustomCompareEffect`](./docs/useCustomCompareEffect.md) — run an `effect` depending on deep comparison of its dependencies
- [**State**](./docs/State.md)
@@ -128,15 +127,28 @@
- [`useGetSet`](./docs/useGetSet.md) — returns state getter `get()` instead of raw state.
- [`useGetSetState`](./docs/useGetSetState.md) — as if [`useGetSet`](./docs/useGetSet.md) and [`useSetState`](./docs/useSetState.md) had a baby.
- [`usePrevious`](./docs/usePrevious.md) — returns the previous state or props. [![][img-demo]](https://codesandbox.io/s/fervent-galileo-krgx6)
+ - [`usePreviousDistinct`](./docs/usePreviousDistinct.md) — like `usePrevious` but with a predicate to determine if `previous` should update.
- [`useObservable`](./docs/useObservable.md) — tracks latest value of an `Observable`.
- [`useRafState`](./docs/useRafState.md) — creates `setState` method which only updates after `requestAnimationFrame`. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-userafstate--demo)
- [`useSetState`](./docs/useSetState.md) — creates `setState` method which works like `this.setState`. [![][img-demo]](https://codesandbox.io/s/n75zqn1xp0)
- [`useStateList`](./docs/useStateList.md) — circularly iterates over an array. [![][img-demo]](https://codesandbox.io/s/bold-dewdney-pjzkd)
- [`useToggle` and `useBoolean`](./docs/useToggle.md) — tracks state of a boolean. [![][img-demo]](https://codesandbox.io/s/focused-sammet-brw2d)
- [`useCounter` and `useNumber`](./docs/useCounter.md) — tracks state of a number. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usecounter--demo)
- - [`useList`](./docs/useList.md) and [`useUpsert`](./docs/useUpsert.md) — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
+ - [`useList`](./docs/useList.md) ~and [`useUpsert`](./docs/useUpsert.md)~ — tracks state of an array. [![][img-demo]](https://codesandbox.io/s/wonderful-mahavira-1sm0w)
- [`useMap`](./docs/useMap.md) — tracks state of an object. [![][img-demo]](https://codesandbox.io/s/quirky-dewdney-gi161)
+ - [`useSet`](./docs/useSet.md) — tracks state of a Set. [![][img-demo]](https://codesandbox.io/s/bold-shtern-6jlgw)
+ - [`useQueue`](./docs/useQueue.md) — implements simple queue.
- [`useStateValidator`](./docs/useStateValidator.md) — tracks state of an object. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatevalidator--demo)
+ - [`useStateWithHistory`](./docs/useStateWithHistory.md) — stores previous state values and provides handles to travel through them. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usestatewithhistory--demo)
+ - [`useMultiStateValidator`](./docs/useMultiStateValidator.md) — alike the `useStateValidator`, but tracks multiple states at a time. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemultistatevalidator--demo)
+ - [`useMediatedState`](./docs/useMediatedState.md) — like the regular `useState` but with mediation by custom function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usemediatedstate--demo)
+ - [`useFirstMountState`](./docs/useFirstMountState.md) — check if current render is first. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-usefirstmountstate--demo)
+ - [`useRendersCount`](./docs/useRendersCount.md) — count component renders. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-userenderscount--demo)
+
+
+- [**Miscellaneous**]()
+ - [`useEnsuredForwardedRef`](./docs/useEnsuredForwardedRef.md) and [`ensuredForwardRef`](./docs/useEnsuredForwardedRef.md) — use a React.forwardedRef safely. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/state-useensuredforwardedref--demo)
+
;
+};
+```
diff --git a/docs/useCustomCompareEffect.md b/docs/useCustomCompareEffect.md
new file mode 100644
index 0000000000..9c90247ec6
--- /dev/null
+++ b/docs/useCustomCompareEffect.md
@@ -0,0 +1,31 @@
+# `useCustomCompareEffect`
+
+A modified useEffect hook that accepts a comparator which is used for comparison on dependencies instead of reference equality.
+
+## Usage
+
+```jsx
+import {useCounter, useDeepCompareEffect} from 'react-use';
+import isEqual from 'lodash/isEqual';
+
+const Demo = () => {
+ const [count, {inc: inc}] = useCounter(0);
+ const options = { step: 2 };
+
+ useCustomCompareEffect(() => {
+ inc(options.step)
+ }, [options], (prevDeps, nextDeps) => isEqual(prevDeps, nextDeps));
+
+ return (
+
+
useCustomCompareEffect with deep comparison: {count}
+
+ );
+};
+```
+
+## Reference
+
+```ts
+useCustomCompareEffect(effect: () => void | (() => void | undefined), deps: any[], depsEqual: (prevDeps: any[], nextDeps: any[]) => boolean);
+```
diff --git a/docs/useDebounce.md b/docs/useDebounce.md
index 20a25b27e6..151e9a2af8 100644
--- a/docs/useDebounce.md
+++ b/docs/useDebounce.md
@@ -7,15 +7,12 @@ The third argument is the array of values that the debounce depends on, in the s
## Usage
```jsx
-import React, { useState } from 'react';
-import { useDebounce } from 'react-use';
-
const Demo = () => {
const [state, setState] = React.useState('Typing stopped');
const [val, setVal] = React.useState('');
const [debouncedValue, setDebouncedValue] = React.useState('');
- useDebounce(
+ const [, cancel] = useDebounce(
() => {
setState('Typing stopped');
setDebouncedValue(val);
@@ -36,7 +33,10 @@ const Demo = () => {
}}
/>
{state}
-
Debounced value: {debouncedValue}
+
+ Debounced value: {debouncedValue}
+
+
);
};
@@ -45,5 +45,17 @@ const Demo = () => {
## Reference
```ts
-useDebounce(fn, ms: number, args: any[]);
+const [
+ isReady: () => boolean | null,
+ cancel: () => void,
+] = useDebounce(fn: Function, ms: number, deps: DependencyList = []);
```
+
+- **`fn`**_`: Function`_ - function that will be called;
+- **`ms`**_`: number`_ - delay in milliseconds;
+- **`deps`**_`: DependencyList`_ - array of values that the debounce depends on, in the same manner as useEffect;
+- **`isReady`**_`: ()=>boolean|null`_ - function returning current debounce state:
+ - `false` - pending
+ - `true` - called
+ - `null` - cancelled
+- **`cancel`**_`: ()=>void`_ - cancel the debounce
diff --git a/docs/useEnsuredForwardedRef.md b/docs/useEnsuredForwardedRef.md
new file mode 100644
index 0000000000..b094a284bc
--- /dev/null
+++ b/docs/useEnsuredForwardedRef.md
@@ -0,0 +1,63 @@
+# `useEnsuredForwardedRef`
+
+React hook to use a ForwardedRef safely.
+
+In some scenarios, you may need to use a _ref_ from inside and outside a component. If that's the case, you should use `React.forwardRef` to pass it through the child component. This is useful when you only want to forward that _ref_ and expose an internal `HTMLelement` to a parent component, for example. However, if you need to manipulate that reference inside a child's lifecycle hook... things get complicated, since you can't always ensure that the _ref_ is being sent by the parent component and if it is not, you will get `undefined` instead of a valid _ref_.
+
+This hook is useful in this specific case, it will __ensure__ that you get a valid reference on the other side.
+
+## Usage
+
+```jsx
+import {ensuredForwardRef} from 'react-use';
+
+const Demo = () => {
+ return (
+
+ );
+};
+
+const Child = ensuredForwardRef((props, ref) => {
+ useEffect(() => {
+ console.log(ref.current.getBoundingClientRect())
+ }, [])
+
+ return (
+
+ );
+});
+```
+
+## Alternative usage
+
+```jsx
+import {useEnsuredForwardedRef} from 'react-use';
+
+const Demo = () => {
+ return (
+
+ );
+};
+
+const Child = React.forwardRef((props, ref) => {
+ // Here `ref` is undefined
+ const ensuredForwardRef = useEnsuredForwardedRef(ref);
+ // ensuredForwardRef will always be a valid reference.
+
+ useEffect(() => {
+ console.log(ensuredForwardRef.current.getBoundingClientRect())
+ }, [])
+
+ return (
+
+ );
+});
+```
+
+## Reference
+
+```ts
+ensuredForwardRef(Component: RefForwardingComponent): ForwardRefExoticComponent & RefAttributes>;
+
+useEnsuredForwardedRef(ref: React.MutableRefObject): React.MutableRefObject;
+```
diff --git a/docs/useFirstMountState.md b/docs/useFirstMountState.md
new file mode 100644
index 0000000000..8d2a737389
--- /dev/null
+++ b/docs/useFirstMountState.md
@@ -0,0 +1,29 @@
+# `useFirstMountState`
+
+Returns `true` if component is just mounted (on first render) and `false` otherwise.
+
+## Usage
+
+```typescript jsx
+import * as React from 'react';
+import { useFirstMountState } from 'react-use';
+
+const Demo = () => {
+ const isFirstMount = useFirstMountState();
+ const update = useUpdate();
+
+ return (
+
+ This component is just mounted: {isFirstMount ? 'YES' : 'NO'}
+
+
+
+ );
+};
+```
+
+## Reference
+
+```typescript
+const isFirstMount: boolean = useFirstMountState();
+```
diff --git a/docs/useList.md b/docs/useList.md
index 2e33e188a5..caffe42f6b 100644
--- a/docs/useList.md
+++ b/docs/useList.md
@@ -1,6 +1,11 @@
# `useList`
-React state hook that tracks a value of an array.
+Tracks an array and provides methods to modify it.
+To cause component re-render you have to use these methods instead of direct interaction with array - it won't cause re-render.
+
+We can ensure that actions object and actions itself will not mutate or change between renders, so there is no need to add it to useEffect dependencies and safe to pass them down to children.
+
+**Note:** `remove` action is deprecated and actually is a copy of `removeAt` action. Within closest updates it will gain different functionality.
## Usage
@@ -8,7 +13,7 @@ React state hook that tracks a value of an array.
import {useList} from 'react-use';
const Demo = () => {
- const [list, { clear, filter, push, remove, set, sort, updateAt, reset }] = useList();
+ const [list, { set, push, updateAt, insertAt, update, updateFirst, upsert, sort, filter, removeAt, clear, reset }] = useList([1, 2, 3, 4, 5]);
return (
@@ -27,6 +32,42 @@ const Demo = () => {
};
```
+## Reference
+```ts
+import {useList} from "react-use";
+
+const [list, {
+ set,
+ push,
+ updateAt,
+ insertAt,
+ update,
+ updateFirst,
+ upsert,
+ sort,
+ filter,
+ removeAt,
+ remove,
+ clear,
+ reset
+}] = useList(array: any[] | ()=> any[]);
+```
+
+- **`list`**_`: T{}`_ — current list;
+- **`set`**_`: (list: T[]) => void;`_ — Set new list instead old one;
+- **`push`**_`: (...items: T[]) => void;`_ — Add item(s) at the end of list;
+- **`updateAt`**_`: (index: number, item: T) => void;`_ — Replace item at given position. If item at given position not exists it will be set;
+- **`insertAt`**_`: (index: number, item: T) => void;`_ — Insert item at given position, all items to the right will be shifted;
+- **`update`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ — Replace all items that matches predicate with given one;
+- **`updateFirst`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ — Replace first item matching predicate with given one;
+- **`upsert`**_`: (predicate: (a: T, b: T) => boolean, newItem: T) => void;`_ — Like `updateFirst` but in case of predicate miss - pushes item to the list;
+- **`sort`**_`: (compareFn?: (a: T, b: T) => number) => void;`_ — Sort list with given sorting function;
+- **`filter`**_`: (callbackFn: (value: T, index?: number, array?: T[]) => boolean, thisArg?: any) => void;`_ — Same as native Array's method;
+- **`removeAt`**_`: (index: number) => void;`_ — Removes item at given position. All items to the right from removed will be shifted;
+- **`remove`**_`: (index: number) => void;`_ — _**DEPRECATED:**_ Use removeAt method instead;
+- **`clear`**_`: () => void;`_ — Make the list empty;
+- **`reset`**_`: () => void;`_ — Reset list to initial value;
+
## Related hooks
- [useUpsert](./useUpsert.md)
diff --git a/docs/useMeasure.md b/docs/useMeasure.md
index 0f574fbcbe..d8e87a0cad 100644
--- a/docs/useMeasure.md
+++ b/docs/useMeasure.md
@@ -12,7 +12,7 @@ const Demo = () => {
return (
-
x: {x}
+
x: {x}
y: {y}
width: {width}
height: {height}
diff --git a/docs/useMediatedState.md b/docs/useMediatedState.md
new file mode 100644
index 0000000000..0779a2e97d
--- /dev/null
+++ b/docs/useMediatedState.md
@@ -0,0 +1,39 @@
+# `useMediatedState`
+
+A lot like the standard `useState`, but with mediation process.
+
+## Usage
+```ts
+import * as React from 'react';
+import { useMediatedState } from '../useMediatedState';
+
+const inputMediator = s => s.replace(/[\s]+/g, ' ');
+const Demo = () => {
+ const [state, setState] = useMediatedState(inputMediator, '');
+
+ return (
+
+
You will not be able to enter more than one space
+ ) => {
+ setState(ev.target.value);
+ }}
+ />
+
+ );
+};
+```
+
+## Reference
+```ts
+const [state, setState] = useMediatedState(
+ mediator: StateMediator,
+ initialState?: S
+);
+```
+
+> Initial state will be set as-is.
+
+In case mediator expects 2 arguments it will receive the `setState` function as second argument, it is useful for async mediators.
+>This hook will not cancel previous mediation when new one been invoked, you have to handle it yourself._
diff --git a/docs/useMount.md b/docs/useMount.md
index 95b53ae8b9..7b357c55ff 100644
--- a/docs/useMount.md
+++ b/docs/useMount.md
@@ -8,7 +8,7 @@ React lifecycle hook that calls a function after the component is mounted. Use `
import {useMount} from 'react-use';
const Demo = () => {
- useMount(() => console.log('MOUNTED'));
+ useMount(() => alert('MOUNTED'));
return null;
};
```
diff --git a/docs/useMultiStateValidator.md b/docs/useMultiStateValidator.md
new file mode 100644
index 0000000000..42de5b1e88
--- /dev/null
+++ b/docs/useMultiStateValidator.md
@@ -0,0 +1,55 @@
+# `useMultiStateValidator`
+
+Each time any of given states changes - validator function is invoked.
+
+## Usage
+```ts
+import * as React from 'react';
+import { useMultiStateValidator } from 'react-use';
+
+const DemoStateValidator = (s: number[]) => [s.every((num: number) => !(num % 2))] as [boolean];
+const Demo = () => {
+ const [state1, setState1] = React.useState(1);
+ const [state2, setState2] = React.useState(1);
+ const [state3, setState3] = React.useState(1);
+ const [[isValid]] = useMultiStateValidator([state1, state2, state3], DemoStateValidator);
+
+ return (
+
+
Below fields will be valid if all of them is even
+ ) => {
+ setState1((ev.target.value as unknown) as number);
+ }}
+ />
+ ) => {
+ setState2((ev.target.value as unknown) as number);
+ }}
+ />
+ ) => {
+ setState3((ev.target.value as unknown) as number);
+ }}
+ />
+ {isValid !== null && {isValid ? 'Valid!' : 'Invalid'}}
+
+ );
+};
+```
+
+## Reference
+```ts
+const [validity, revalidate] = useStateValidator(
+ state: any[] | { [p: string]: any } | { [p: number]: any },
+ validator: (state, setValidity?)=>[boolean|null, ...any[]],
+ initialValidity: any = [undefined]
+);
+```
+- **`state`**_`: any[] | { [p: string]: any } | { [p: number]: any }`_ can be both an array or object. It's _values_ will be used as a deps for inner `useEffect`.
+- **`validity`**_`: [boolean|null, ...any[]]`_ result of validity check. First element is strictly nullable boolean, but others can contain arbitrary data;
+- **`revalidate`**_`: ()=>void`_ runs validator once again
+- **`validator`**_`: (state, setValidity?)=>[boolean|null, ...any[]]`_ should return an array suitable for validity state described above;
+ - `states` - current states values as the've been passed to the hook;
+ - `setValidity` - if defined hook will not trigger validity change automatically. Useful for async validators;
+- `initialValidity` - validity value which set when validity is nt calculated yet;
diff --git a/docs/useQueue.md b/docs/useQueue.md
new file mode 100644
index 0000000000..ef688bb8fd
--- /dev/null
+++ b/docs/useQueue.md
@@ -0,0 +1,26 @@
+# `useQueue`
+
+React state hook implements simple FIFO queue.
+
+
+## Usage
+
+```jsx
+import { useQueue } from 'react-use';
+
+const Demo = () => {
+ const { add, remove, first, last, size } = useQueue();
+
+ return (
+
+
+
first: {first}
+
last: {last}
+
size: {size}
+
+
+
+
+ );
+};
+```
diff --git a/docs/useRefMounted.md b/docs/useRefMounted.md
deleted file mode 100644
index 0e7d708eb5..0000000000
--- a/docs/useRefMounted.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# `useRefMounted`
-
->**DEPRECATED**
->This method is obsolete, use `useMountedState` instead.
-
-Lifecycle hook that tracks if component is mounted. Returns a ref, which has a
-boolean `.current` property.
-
-
-## Usage
-
-```jsx
-import {useRefMounted} from 'react-use';
-
-const Demo = () => {
- const refMounted = useRefMounted();
-
- useEffect(() => {
- setTimeout(() => {
- if (refMounted.current) {
- // ...
- } else {
- // ...
- }
- }, 1000);
- });
-};
-```
diff --git a/docs/useRendersCount.md b/docs/useRendersCount.md
new file mode 100644
index 0000000000..05f6111125
--- /dev/null
+++ b/docs/useRendersCount.md
@@ -0,0 +1,29 @@
+# `useRendersCount`
+
+Tracks compontent's renders count including the first render.
+
+## Usage
+
+```typescript jsx
+import * as React from 'react';
+import { useRendersCount } from "react-use";
+
+const Demo = () => {
+ const update = useUpdate();
+ const rendersCount = useRendersCount();
+
+ return (
+
+ Renders count: {rendersCount}
+
+
+
+ );
+};
+```
+
+## Reference
+
+```typescript
+const rendersCount: number = useRendersCount();
+```
diff --git a/docs/useScrollbarWidth.md b/docs/useScrollbarWidth.md
new file mode 100644
index 0000000000..b3246dfa91
--- /dev/null
+++ b/docs/useScrollbarWidth.md
@@ -0,0 +1,25 @@
+# `useScrollbarWidth`
+
+Hook that will return current browser's scrollbar width.
+In case hook been called before DOM ready, it will return `undefined` and will cause re-render on first available RAF.
+> **_NOTE:_** it does not work (return 0) for mobile devices, because their scrollbar width can not be determined.
+
+## Usage
+
+```jsx
+const Demo = () => {
+ const sbw = useScrollbarWidth();
+
+ return (
+
+ {sbw === undefined ? `DOM is not ready yet, SBW detection delayed` : `Browser's scrollbar width is ${sbw}px`}
+
+ );
+};
+```
diff --git a/docs/useShallowCompareEffect.md b/docs/useShallowCompareEffect.md
new file mode 100644
index 0000000000..4ece957c96
--- /dev/null
+++ b/docs/useShallowCompareEffect.md
@@ -0,0 +1,30 @@
+# `useShallowCompareEffect`
+
+A modified useEffect hook that is using shallow comparison on each of its dependencies instead of reference equality.
+
+## Usage
+
+```jsx
+import {useCounter, useShallowCompareEffect} from 'react-use';
+
+const Demo = () => {
+ const [count, {inc: inc}] = useCounter(0);
+ const options = { step: 2 };
+
+ useShallowCompareEffect(() => {
+ inc(options.step)
+ }, [options]);
+
+ return (
+
+
useShallowCompareEffect: {count}
+
+ );
+};
+```
+
+## Reference
+
+```ts
+useShallowCompareEffect(effect: () => void | (() => void | undefined), deps: any[]);
+```
diff --git a/docs/useStateList.md b/docs/useStateList.md
index b9c91885a7..5d1fa27807 100644
--- a/docs/useStateList.md
+++ b/docs/useStateList.md
@@ -1,25 +1,52 @@
# `useStateList`
-React state hook that circularly iterates over an array.
+Provides handles for circular iteration over states list.
+Supports forward and backward iterations and arbitrary position set.
## Usage
```jsx
import { useStateList } from 'react-use';
+import { useRef } from 'react';
const stateSet = ['first', 'second', 'third', 'fourth', 'fifth'];
const Demo = () => {
- const {state, prev, next} = useStateList(stateSet);
+ const { state, prev, next, setStateAt, setState, currentIndex } = useStateList(stateSet);
+ const indexInput = useRef(null);
+ const stateInput = useRef(null);
return (
-
{state}
+
+ {state} [index: {currentIndex}]
+
+
+
+
+
+
+
+
);
};
```
-> If the `stateSet` is changed by a shorter one the hook will select the last element of it.
+## Reference
+
+```ts
+const { state, currentIndex, prev, next, setStateAt, setState } = useStateList(stateSet: T[] = []);
+```
+
+If `stateSet` changed, became shorter than before and `currentIndex` left in shrinked gap - the last element of list will be taken as current.
+
+- **`state`**_`: T`_ — current state value;
+- **`currentIndex`**_`: number`_ — current state index;
+- **`prev()`**_`: void`_ — switches state to the previous one. If first element selected it will switch to the last one;
+- **`nexct()`**_`: void`_ — switches state to the next one. If last element selected it will switch to the first one;
+- **`setStateAt(newIndex: number)`**_`: void`_ — set the arbitrary state by index. Indexes are looped, and can be negative.
+_4ex:_ if list contains 5 elements, attempt to set index 9 will bring use to the 5th element, in case of negative index it will start counting from the right, so -17 will bring us to the 4th element.
+- **`setState(state: T)`**_`: void`_ — set the arbitrary state value that exists in `stateSet`. _In case new state does not exists in `stateSet` an Error will be thrown._
diff --git a/docs/useStateWithHistory.md b/docs/useStateWithHistory.md
new file mode 100644
index 0000000000..5d6ac85c09
--- /dev/null
+++ b/docs/useStateWithHistory.md
@@ -0,0 +1,33 @@
+# `useStateHistory`
+
+Stores defined amount of previous state values and provides handles to travel through them.
+
+## Usage
+
+## Reference
+
+```typescript
+const [state, setState, stateHistory] = useStateWithHistory(
+ initialState?: S | (()=>S),
+ historyCapacity?: number = 10,
+ initialHistory?: S
+);
+```
+
+- **`state`**, **`setState`** and **`initialState`** are exactly the same with native React's `useState` hook;
+- **`historyCapacity`** - amount of history entries that hold by storage;
+- **`initialHistory`** - if defined it will be used as initial history value, otherwise history will equals `[ initialState ]`.
+Initial state will not be pushed to initial history.
+If entries amount is greater than `historyCapacity` parameter it wont be modified on init but will be trimmed on next `setState`;
+- **`stateHistory`** - an object containing history state:
+ - **`history`**_`: S[]`_ - an array holding history entries. _I will have the same ref all the time so pe careful with that one!_;
+ - **`position`**_`: number`_ - current position _index_ in history;
+ - **`capacity`**_`: number = 10`_ - maximum amount of history entries;
+ - **`back`**_`: (amount?: number) => void`_ - go back in state history, it will cause `setState` invoke and component re-render.
+ If first element of history reached, the call will have no effect;
+ - **`forward`**_`: (amount?: number) => void`_ - go forward in state history, it will cause `setState` invoke and component re-render.
+ If last element of history reached, the call will have no effect;
+ - **`go`**_`: (position: number) => void`_ - go to arbitrary position in history.
+ In case `position` is non-negative ot will count elements from beginning.
+ Negative `position` will cause elements counting from the end, so `go(-2)` equals `go(history.length - 1)`;
+
diff --git a/docs/useUnmount.md b/docs/useUnmount.md
index 83dc772219..c0a3e6c85b 100644
--- a/docs/useUnmount.md
+++ b/docs/useUnmount.md
@@ -8,7 +8,7 @@ React lifecycle hook that calls a function when the component will unmount. Use
import {useUnmount} from 'react-use';
const Demo = () => {
- useUnmount(() => console.log('UNMOUNTED'));
+ useUnmount(() => alert('UNMOUNTED'));
return null;
};
```
diff --git a/docs/useUnmountPromise.md b/docs/useUnmountPromise.md
new file mode 100644
index 0000000000..5a129cb936
--- /dev/null
+++ b/docs/useUnmountPromise.md
@@ -0,0 +1,30 @@
+# `useUnmountPromise`
+
+A life-cycle hook that provides a higher order promise that does not resolve if component un-mounts.
+
+
+## Usage
+
+```ts
+import useUnmountPromise from 'react-use/lib/useUnmountPromise';
+
+const Demo = () => {
+ const mounted = useUnmountPromise();
+ useEffect(async () => {
+ await mounted(someFunction()); // Will not resolve if component un-mounts.
+ });
+};
+```
+
+
+## Reference
+
+```ts
+const mounted = useUnmountPromise();
+
+mounted(promise);
+mounted(promise, onError);
+```
+
+- `onError` — if promise rejects after the component is unmounted, `onError`
+ callback is called with the error.
diff --git a/docs/useUpsert.md b/docs/useUpsert.md
index 48c3de554c..25fe7d71fd 100644
--- a/docs/useUpsert.md
+++ b/docs/useUpsert.md
@@ -1,5 +1,8 @@
# `useUpsert`
+> DEPRECATED!
+> Use `useList` hook's upsert action instead
+
Superset of [`useList`](./useList.md). Provides an additional method to upsert (update or insert) an element into the list.
## Usage
diff --git a/docs/useVibrate.md b/docs/useVibrate.md
new file mode 100644
index 0000000000..957d01149f
--- /dev/null
+++ b/docs/useVibrate.md
@@ -0,0 +1,31 @@
+# `useVibrate`
+
+React UI hook to provide physical feedback with device vibration hardware using the [Vibration API](https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API).
+
+## Usage
+
+```jsx
+import {useVibrate} from 'react-use';
+
+const Demo = () => {
+ const [vibrating, toggleVibrating] = useToggle(false);
+
+ useVibrate(vibrating, [300, 100, 200, 100, 1000, 300], false);
+
+ return (
+
+
+
+ );
+};
+```
+
+## Reference
+
+```ts
+useVibrate(
+ enabled: boolean = true,
+ pattern: number | number[] = [1000, 1000],
+ loop: boolean = true
+): void;
+```
diff --git a/docs/useWait.md b/docs/useWait.md
deleted file mode 100644
index 99f62ae2d2..0000000000
--- a/docs/useWait.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# `useWait`
-
-`useWait` is a React Hook helps to manage multiple loading states on the page without any conflict. It's based on a very simple idea that manages an `Array` of multiple loading states. The built-in `Wait` component listens its registered loader and immediately become loading state.
-
-
-## Usage
-
-```jsx
-import { useWait } from 'react-use'
-
-function UserCreateButton() {
- const { startWaiting, endWaiting, isWaiting, Wait } = useWait();
-
- return (
-