From d9f21e30e16185ed90e5a815ee5cb974544b96d7 Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 25 Aug 2019 12:52:03 +0200 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20useHarmonicInt?= =?UTF-8?q?ervalFn()=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + .../setHarmonicIntervalFn.story.tsx | 63 +++++++++++++++++++ src/index.ts | 1 + src/useHarmonicIntervalFn.ts | 20 ++++++ yarn.lock | 5 ++ 5 files changed, 90 insertions(+) create mode 100644 src/__stories__/setHarmonicIntervalFn.story.tsx create mode 100644 src/useHarmonicIntervalFn.ts diff --git a/package.json b/package.json index 3502ce15..c112998b 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "react-fast-compare": "^2.0.4", "react-wait": "^0.3.0", "screenfull": "^4.1.0", + "set-harmonic-interval": "^1.0.0", "throttle-debounce": "^2.0.1", "ts-easing": "^0.2.0" }, diff --git a/src/__stories__/setHarmonicIntervalFn.story.tsx b/src/__stories__/setHarmonicIntervalFn.story.tsx new file mode 100644 index 00000000..f1ba1e5d --- /dev/null +++ b/src/__stories__/setHarmonicIntervalFn.story.tsx @@ -0,0 +1,63 @@ +import { storiesOf } from '@storybook/react'; +import * as React from 'react'; +import { useHarmonicIntervalFn, useInterval, useTimeoutFn } from '..'; +import ShowDocs from './util/ShowDocs'; + +const Clock: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) => { + const [count, setCount] = React.useState(0); + useInt(() => { + setCount(cnt => cnt + 1); + }, 1000); + + let m: number | string = Math.floor(count / 60); + let s: number | string = count % 60; + + m = m < 10 ? '0' + m : String(m); + s = s < 10 ? '0' + s : String(s); + + const style: React.CSSProperties = { + padding: '20px', + border: '1px solid #fafafa', + float: 'left', + fontFamily: 'monospace', + }; + + return
{m + ':' + s}
; +}; + +const Demo: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) => { + const [showSecondClock, setShowSecondClock] = React.useState(false); + useTimeoutFn(() => { + setShowSecondClock(true); + }, 500); + + const headingStyle: React.CSSProperties = { + fontFamily: 'sans', + fontSize: '20px', + padding: '30px 0 0', + }; + + const rowStyle: React.CSSProperties = { + width: '100%', + clear: 'both', + }; + + return ( + <> +
+

{useInt.name}

+ + {showSecondClock ? : null} +
+ + ); +}; + +storiesOf('Side effects|useHarmonicIntervalFn', module) + .add('Docs', () => ) + .add('Demo', () => ( + <> + + + + )); diff --git a/src/index.ts b/src/index.ts index 644f587e..589c353f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ export { default as useFullscreen } from './useFullscreen'; export { default as useGeolocation } from './useGeolocation'; export { default as useGetSet } from './useGetSet'; export { default as useGetSetState } from './useGetSetState'; +export { default as useHarmonicIntervalFn } from './useHarmonicIntervalFn'; export { default as useHover } from './useHover'; export { default as useHoverDirty } from './useHoverDirty'; export { default as useIdle } from './useIdle'; diff --git a/src/useHarmonicIntervalFn.ts b/src/useHarmonicIntervalFn.ts new file mode 100644 index 00000000..d591a32d --- /dev/null +++ b/src/useHarmonicIntervalFn.ts @@ -0,0 +1,20 @@ +import { useEffect, useRef } from 'react'; +import { setHarmonicInterval, clearHarmonicInterval } from 'set-harmonic-interval'; + +const useHarmonicIntervalFn = (fn: Function, delay: number | null = 0) => { + const latestCallback = useRef(() => {}); + + useEffect(() => { + latestCallback.current = fn; + }); + + useEffect(() => { + if (delay !== null) { + const interval = setHarmonicInterval(() => latestCallback.current(), delay); + return () => clearHarmonicInterval(interval); + } + return undefined; + }, [delay]); +}; + +export default useHarmonicIntervalFn; diff --git a/yarn.lock b/yarn.lock index aa473406..d46a2730 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11062,6 +11062,11 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-harmonic-interval@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.0.tgz#2759658395579fc336b9cd026eefe1ad9e742f9b" + integrity sha512-RJtrhB5G10e5A1auBv/jHGq0KWfHH8PAb4ln4+kjiHS46aAP12rSdarSj9GDlxQ3QULA2pefEDpm9Y1Xnz+eng== + set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" From e6dd5de395ea686a891e359cf52e7536cb5454d5 Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 25 Aug 2019 13:03:01 +0200 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20add=20useHarmo?= =?UTF-8?q?nicIntervalFn()=20hook=20documentations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/useHarmonicIntervalFn.md | 14 ++++++++++++++ ...n.story.tsx => useHarmonicIntervalFn.story.tsx} | 12 +++++++++--- src/__stories__/useInterval.story.tsx | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 docs/useHarmonicIntervalFn.md rename src/__stories__/{setHarmonicIntervalFn.story.tsx => useHarmonicIntervalFn.story.tsx} (89%) diff --git a/README.md b/README.md index 8e36339e..a41eeb41 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@
- [**Animations**](./docs/Animations.md) - [`useRaf`](./docs/useRaf.md) — re-renders component on each `requestAnimationFrame`. - - [`useInterval`](./docs/useInterval.md) — re-renders component on a set interval using `setInterval`. + - [`useInterval`](./docs/useInterval.md) and [`useHarmonicIntervalFn`](./docs/useHarmonicIntervalFn.md) — re-renders component on a set interval using `setInterval`. - [`useSpring`](./docs/useSpring.md) — interpolates number over time according to spring dynamics. - [`useTimeout`](./docs/useTimeout.md) — re-renders component after a timeout. - [`useTimeoutFn`](./docs/useTimeoutFn.md) — calls given function after a timeout. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/animation-usetimeoutfn--demo) diff --git a/docs/useHarmonicIntervalFn.md b/docs/useHarmonicIntervalFn.md new file mode 100644 index 00000000..47e3620f --- /dev/null +++ b/docs/useHarmonicIntervalFn.md @@ -0,0 +1,14 @@ +# `useHarmonicIntervalFn` + +Same as [`useInterval`](./useInterval.md) hook, but triggers all effects with the same delay +at the same time. + +For example, this allows you to create ticking clocks on the page which re-render second counter +all at the same time. + + +## Reference + +```js +useHarmonicIntervalFn(fn, delay?: number) +``` diff --git a/src/__stories__/setHarmonicIntervalFn.story.tsx b/src/__stories__/useHarmonicIntervalFn.story.tsx similarity index 89% rename from src/__stories__/setHarmonicIntervalFn.story.tsx rename to src/__stories__/useHarmonicIntervalFn.story.tsx index f1ba1e5d..db6e28fd 100644 --- a/src/__stories__/setHarmonicIntervalFn.story.tsx +++ b/src/__stories__/useHarmonicIntervalFn.story.tsx @@ -16,7 +16,7 @@ const Clock: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) = s = s < 10 ? '0' + s : String(s); const style: React.CSSProperties = { - padding: '20px', + padding: '20px 5px', border: '1px solid #fafafa', float: 'left', fontFamily: 'monospace', @@ -34,7 +34,8 @@ const Demo: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) => const headingStyle: React.CSSProperties = { fontFamily: 'sans', fontSize: '20px', - padding: '30px 0 0', + padding: '0', + lineHeight: '1.5em', }; const rowStyle: React.CSSProperties = { @@ -53,11 +54,16 @@ const Demo: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) => ); }; -storiesOf('Side effects|useHarmonicIntervalFn', module) +storiesOf('Animation|useHarmonicIntervalFn', module) .add('Docs', () => ) .add('Demo', () => ( <> +
+
+
+
+
)); diff --git a/src/__stories__/useInterval.story.tsx b/src/__stories__/useInterval.story.tsx index e5cd0f16..7ac3d37c 100644 --- a/src/__stories__/useInterval.story.tsx +++ b/src/__stories__/useInterval.story.tsx @@ -28,6 +28,6 @@ const Demo = () => { ); }; -storiesOf('Side effects|useInterval', module) +storiesOf('Animation|useInterval', module) .add('Docs', () => ) .add('Demo', () => ); From 3bb525a5e1e2cfb19c8f0743827097e3449bf552 Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 25 Aug 2019 13:05:10 +0200 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20=E2=9C=8F=EF=B8=8F=20fix=20Storyboo?= =?UTF-8?q?k=20useHarmonicIntervalFn()=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__stories__/useHarmonicIntervalFn.story.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__stories__/useHarmonicIntervalFn.story.tsx b/src/__stories__/useHarmonicIntervalFn.story.tsx index db6e28fd..0a0c32fc 100644 --- a/src/__stories__/useHarmonicIntervalFn.story.tsx +++ b/src/__stories__/useHarmonicIntervalFn.story.tsx @@ -55,7 +55,7 @@ const Demo: React.FC<{ useInt: typeof useHarmonicIntervalFn }> = ({ useInt }) => }; storiesOf('Animation|useHarmonicIntervalFn', module) - .add('Docs', () => ) + .add('Docs', () => ) .add('Demo', () => ( <>