From 2f0a4af970e55a20181359ee4b9555a8d09114d5 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 17:09:20 -0500 Subject: [PATCH 01/22] Add useInterval --- src/useInterval/index.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/useInterval/index.ts diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts new file mode 100644 index 000000000..1348d9cfa --- /dev/null +++ b/src/useInterval/index.ts @@ -0,0 +1,34 @@ +import { useEffect, useRef } from "react" + +// Ref: https://github.com/Hermanya/use-interval/blob/master/src/index.tsx + +// tslint:disable-next-line +const noop = () => {} + +export const useInterval = (callback: () => void, delay: number | null, immediate?: boolean) => { + const savedCallback = useRef(noop) + + // Remember the latest callback. + useEffect(() => { + savedCallback.current = callback + }) + + // Execute callback if immediate is set. + useEffect(() => { + if (immediate && delay !== null) { + savedCallback.current() + } + }, [immediate]) + + // Set up the interval. + useEffect(() => { + if (delay === null) { + return undefined + } + const tick = () => savedCallback.current() + const id = setInterval(tick, delay) + return () => clearInterval(id) + }, [delay]) +} + +export default useInterval From 11d0eb917e76d0147a41e31733e4b60f6cf7ea24 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 17:11:44 -0500 Subject: [PATCH 02/22] Add hooks and optimize a bit --- src/Splash/Splash.Animation.tsx | 110 +++++++++++++++++--------------- src/Splash/Splash.tsx | 58 +++++------------ 2 files changed, 74 insertions(+), 94 deletions(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index 42c994e26..c1b48f884 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -1,8 +1,10 @@ -import * as React from "react" - +import React, { useState } from "react" +import useInterval from "../useInterval" +import useWindowSize from "../useWindowSize" import styled from "../utils/styled" export interface Props { + fullscreen?: boolean size?: number } @@ -34,73 +36,75 @@ const bounce = (coord: number): number => { return coord } -const Container = styled("div")<{ size: number }>(({ size }: { size: number }) => ({ - width: size, - height: size, +const Container = styled("div")({ position: "absolute", top: "50%", left: "50%", transform: "translate3d(-50%, -50%, 0)", -})) +}) + +/// Move highly highly dynamic style out of css-js to prevent uneeded classname generation -const Box = styled("div")<{ x: number; y: number }>(({ x, y }) => ({ +const Box = styled("div")({ position: "absolute", transition: "all 0.5s ease-in-out", - top: `calc(${(x / (squares - 1)) * 100}% + 4px)`, - left: `calc(${(y / (squares - 1)) * 100}% + 4px)`, + borderRadius: 6, width: `calc(${100 / (squares - 1)}% - 8px)`, height: `calc(${100 / (squares - 1)}% - 8px)`, backgroundColor: "rgba(255, 255, 255, 0.06)", -})) - -class Animation extends React.Component { - public state = { - animationStep: 0, - coordinates: Array.apply(null, { length: boxes }) - .map(Number.call, Number) - .map(() => ({ x: integerRandom(squares), y: integerRandom(squares) })), - } +}) - public animationInterval?: number - - // Shift the coordinate of every third tile in a random direction. - // Each animation shifts a different set of tiles. - public shiftSomeTiles() { - this.setState(prevState => ({ - animationStep: prevState.animationStep + 1, - coordinates: prevState.coordinates.map((coord: { x: number; y: number }, index: number) => { - if (index % 3 === prevState.animationStep % 3) { - const dx = integerRandom(3) - 1 - const dy = integerRandom(3) - 1 - return { - x: bounce(coord.x + dx), - y: bounce(coord.y - dy), - } - } - return coord - }), - })) - } +const initialState = { + animationStep: 0, + coordinates: Array.apply(null, Array(boxes)) + .map((_: any, i: number) => i) // Fixes typescript Error + .map(() => ({ x: integerRandom(squares), y: integerRandom(squares) })), +} - public componentDidMount() { - this.animationInterval = window.setInterval(this.shiftSomeTiles.bind(this), 5000) - } +const Animation: React.FC = ({ fullscreen, size }) => { + let containerSize = size || 600 - public componentWillUnmount() { - clearInterval(this.animationInterval) + if (fullscreen) { + const windowSize = useWindowSize() + containerSize = Math.max(windowSize.width, windowSize.height) - 20 } - public render() { - const size = this.props.size || 600 - return ( - - {this.state.coordinates.map((coord: { x: number; y: number }, index: number) => ( - - ))} - - ) - } + const [state, updateAnimation] = useState(initialState) + useInterval( + () => { + updateAnimation({ + animationStep: state.animationStep + 1, + coordinates: state.coordinates.map((coord: { x: number; y: number }, index: number) => { + if (index % 3 === state.animationStep % 3) { + const dx = integerRandom(3) - 1 + const dy = integerRandom(3) - 1 + return { + x: bounce(coord.x + dx), + y: bounce(coord.y - dy), + } + } + return coord + }), + }) + }, + 5000, + true, + ) + + return ( + + {state.coordinates.map((coord: { x: number; y: number }, index: number) => ( + + ))} + + ) } export default Animation diff --git a/src/Splash/Splash.tsx b/src/Splash/Splash.tsx index c5552242a..cdc187688 100644 --- a/src/Splash/Splash.tsx +++ b/src/Splash/Splash.tsx @@ -2,6 +2,7 @@ import * as React from "react" import { readableTextColor } from "../utils" import { expandColor, OperationalStyleConstants } from "../utils/constants" + import styled from "../utils/styled" import Animation from "./Splash.Animation" import OperationalLogo from "./Splash.Logo" @@ -89,47 +90,22 @@ const Static = styled("div")` } ` -class Splash extends React.Component> { - public readonly state = { - animationSize: Math.max(window.innerWidth, window.innerHeight), - } - - public static defaultProps = { - color: "#fff", - } - - public handleResize = () => { - this.setState({ - animationSize: Math.max(window.innerWidth, window.innerHeight) as number, - }) - } - - public componentDidMount() { - window.addEventListener("resize", this.handleResize) - } - - public componentWillUnmount() { - window.removeEventListener("resize", this.handleResize) - } - - public render() { - const { logo, color } = this.props - return ( - - - - - - -

{this.props.title}

-
{this.props.actions}
-
-
- {this.props.children} -
-
- ) - } +const Splash: React.FC = ({ color, logo, children, title, actions }) => { + return ( + + + + + + +

{title}

+
{actions}
+
+
+ {children} +
+
+ ) } export default Splash From 160e8f16a2141ae461cd1af9a76dbf37ddb30b97 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 17:51:29 -0500 Subject: [PATCH 03/22] Change to function to help aid trace error --- src/useInterval/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 1348d9cfa..3eec64983 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -5,7 +5,7 @@ import { useEffect, useRef } from "react" // tslint:disable-next-line const noop = () => {} -export const useInterval = (callback: () => void, delay: number | null, immediate?: boolean) => { +export function useInterval(callback: () => void, delay: number | null, immediate?: boolean) { const savedCallback = useRef(noop) // Remember the latest callback. From 8b23545b9417442c026f6a36c01f22b1c461aaa6 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 17:51:43 -0500 Subject: [PATCH 04/22] Create README.md --- src/useInterval/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/useInterval/README.md diff --git a/src/useInterval/README.md b/src/useInterval/README.md new file mode 100644 index 000000000..521f0a1aa --- /dev/null +++ b/src/useInterval/README.md @@ -0,0 +1,18 @@ +## Usage + +This hook sets up an interval and clears it after unmounting + +```jsx +const MyComponent = () => { + let [count, setCount] = React.useState(0) + + useInterval(() => { + // Your custom logic here + setCount(count + 1) + }, 1000) + + return

{count}

+} + +; +``` From 285a5f993f59f5b12922caf2971273d2aaa4a377 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 17:52:17 -0500 Subject: [PATCH 05/22] add tests --- src/useInterval/useInterval.test.tsx | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/useInterval/useInterval.test.tsx diff --git a/src/useInterval/useInterval.test.tsx b/src/useInterval/useInterval.test.tsx new file mode 100644 index 000000000..4ebab91d8 --- /dev/null +++ b/src/useInterval/useInterval.test.tsx @@ -0,0 +1,75 @@ +import React from "react" +import { cleanup, render } from "react-testing-library" + +import useInterval, { useInterval as namedHook } from "." + +// ref https://github.com/Hermanya/use-interval/blob/master/src/test.tsx + +beforeEach(cleanup) + +const MyComponent: React.FC<{ fn: () => void; delay: number | null; immediate?: boolean }> = ({ + fn, + delay, + immediate, +}) => { + useInterval(fn, delay, immediate) + return A Interval is running +} + +describe("useInterval", () => { + it("exports a function (default)", () => { + expect(useInterval).toBeInstanceOf(Function) + }) + it("exports a function (named)", () => { + expect(namedHook).toBeInstanceOf(Function) + }) + it("hooks identity are the same", () => { + expect(useInterval).toBe(namedHook) + }) + it("is a named function", () => { + // aids stack trace debugging. + expect(useInterval.name).toBe("useInterval") + }) + + describe("regular mode (delayed)", () => { + jest.useFakeTimers() + + const fn: () => void = jest.fn() + const { container } = render() + + expect(fn).toBeCalledTimes(0 /* not called on first render */) + jest.advanceTimersByTime(500) + expect(fn).toBeCalledTimes(1) + jest.advanceTimersByTime(1500) + expect(fn).toBeCalledTimes(4) + + test("cancels interval when delay is null", () => { + render(, { container }) + jest.advanceTimersByTime(1500) + expect(fn).toBeCalledTimes(4) + }) + + jest.clearAllTimers() + }) + + describe("immediate mode", () => { + jest.useFakeTimers() + + const fn = jest.fn() + const { container } = render() + + expect(fn).toBeCalledTimes(1 /* called immediatelly on render */) + jest.advanceTimersByTime(500) + expect(fn).toBeCalledTimes(2) + jest.advanceTimersByTime(1500) + expect(fn).toBeCalledTimes(5) + + it("cancels interval when delay is null", () => { + render(, { container }) + jest.advanceTimersByTime(1500) + expect(fn).toBeCalledTimes(5) + }) + + jest.clearAllTimers() + }) +}) From fcba4244189b8be58332fd19ffb2b8a7157b8804 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 27 Feb 2019 18:20:04 -0500 Subject: [PATCH 06/22] Added comment to remove styleguidist warning --- src/useInterval/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 3eec64983..4ed131c43 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -5,6 +5,9 @@ import { useEffect, useRef } from "react" // tslint:disable-next-line const noop = () => {} +/** + * useInterval + */ export function useInterval(callback: () => void, delay: number | null, immediate?: boolean) { const savedCallback = useRef(noop) From 26f8582612877676a8ec7093a6127b05c4fac49e Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Thu, 28 Feb 2019 15:09:59 -0500 Subject: [PATCH 07/22] suggestions from code review:useInterval Co-Authored-By: JoshRosenstein <32781407+JoshRosenstein@users.noreply.github.com> --- src/useInterval/index.ts | 7 +++++-- src/useInterval/useInterval.test.tsx | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 4ed131c43..395e1fe12 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -6,12 +6,15 @@ import { useEffect, useRef } from "react" const noop = () => {} /** - * useInterval + * Hook version of setInterval. Pass null to the delay to cancel an execution. */ export function useInterval(callback: () => void, delay: number | null, immediate?: boolean) { const savedCallback = useRef(noop) // Remember the latest callback. + // useEffect has no second argument so it will be executed after each render + // but we don't want to change this value directly in the body of the render function, + // because render should be pure function useEffect(() => { savedCallback.current = callback }) @@ -29,7 +32,7 @@ export function useInterval(callback: () => void, delay: number | null, immediat return undefined } const tick = () => savedCallback.current() - const id = setInterval(tick, delay) + const id = setInterval(() => savedCallback.current(), delay) return () => clearInterval(id) }, [delay]) } diff --git a/src/useInterval/useInterval.test.tsx b/src/useInterval/useInterval.test.tsx index 4ebab91d8..ccb3f7f9b 100644 --- a/src/useInterval/useInterval.test.tsx +++ b/src/useInterval/useInterval.test.tsx @@ -13,7 +13,7 @@ const MyComponent: React.FC<{ fn: () => void; delay: number | null; immediate?: immediate, }) => { useInterval(fn, delay, immediate) - return A Interval is running + return An Interval is running } describe("useInterval", () => { From 0b068bda647b416163001759cb705a4a4f446148 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Thu, 28 Feb 2019 15:23:16 -0500 Subject: [PATCH 08/22] useInterval updates --- src/useInterval/index.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 395e1fe12..51979eab7 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -1,9 +1,7 @@ +import { noop } from "lodash" import { useEffect, useRef } from "react" -// Ref: https://github.com/Hermanya/use-interval/blob/master/src/index.tsx - -// tslint:disable-next-line -const noop = () => {} +// From: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ /** * Hook version of setInterval. Pass null to the delay to cancel an execution. @@ -13,28 +11,29 @@ export function useInterval(callback: () => void, delay: number | null, immediat // Remember the latest callback. // useEffect has no second argument so it will be executed after each render - // but we don't want to change this value directly in the body of the render function, + // but we don't want to change this value directly in the body of the render function, // because render should be pure function + + // After every render, save the latest callback into our ref. useEffect(() => { savedCallback.current = callback }) - // Execute callback if immediate is set. useEffect(() => { if (immediate && delay !== null) { savedCallback.current() } - }, [immediate]) + }, [immediate]) // when immediate changes, we want to restart the timer // Set up the interval. useEffect(() => { if (delay === null) { return undefined } - const tick = () => savedCallback.current() - const id = setInterval(() => savedCallback.current(), delay) + // we can read and call latest callback from inside our interval: + const id = setInterval(() => savedCallback.current(), delay) return () => clearInterval(id) - }, [delay]) + }, [delay]) // when delay changes, we want to restart the timer } export default useInterval From 9205d911648ffd140f29f622025c291a988e0f18 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Thu, 28 Feb 2019 15:27:26 -0500 Subject: [PATCH 09/22] Remove useWindowSize, replaced with css Trick- change isFullscreen --- src/Splash/Splash.Animation.tsx | 53 ++++++++++++++++++++++----------- src/Splash/Splash.tsx | 3 +- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index c1b48f884..a9ce982e8 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -1,10 +1,9 @@ -import React, { useState } from "react" +import React, { useCallback, useState } from "react" import useInterval from "../useInterval" -import useWindowSize from "../useWindowSize" import styled from "../utils/styled" export interface Props { - fullscreen?: boolean + isFullscreen?: boolean size?: number } @@ -36,19 +35,30 @@ const bounce = (coord: number): number => { return coord } +// css Hack so we dont need to worry about max(window.height,window.width) +const FullScreenWrap = styled("div")({ + position: "absolute", + width: "100%", + ":after": { + content: "''", + display: "block", + paddingBottom: "100%", + }, +}) + const Container = styled("div")({ position: "absolute", top: "50%", left: "50%", transform: "translate3d(-50%, -50%, 0)", + width: "100%", + height: "100%", }) /// Move highly highly dynamic style out of css-js to prevent uneeded classname generation - const Box = styled("div")({ position: "absolute", transition: "all 0.5s ease-in-out", - borderRadius: 6, width: `calc(${100 / (squares - 1)}% - 8px)`, height: `calc(${100 / (squares - 1)}% - 8px)`, @@ -57,20 +67,15 @@ const Box = styled("div")({ const initialState = { animationStep: 0, - coordinates: Array.apply(null, Array(boxes)) - .map((_: any, i: number) => i) // Fixes typescript Error - .map(() => ({ x: integerRandom(squares), y: integerRandom(squares) })), + coordinates: Array.from(Array(boxes), (_, index) => index).map(() => ({ + x: integerRandom(squares), + y: integerRandom(squares), + })), } -const Animation: React.FC = ({ fullscreen, size }) => { - let containerSize = size || 600 - - if (fullscreen) { - const windowSize = useWindowSize() - containerSize = Math.max(windowSize.width, windowSize.height) - 20 - } - +const Animation: React.FC = ({ isFullscreen, size = 600 }) => { const [state, updateAnimation] = useState(initialState) + useInterval( () => { updateAnimation({ @@ -92,8 +97,20 @@ const Animation: React.FC = ({ fullscreen, size }) => { true, ) + const Wrap = useCallback( + ({ children }) => + isFullscreen ? ( + + {children} + + ) : ( + {children} + ), + [isFullscreen, size], + ) + return ( - + {state.coordinates.map((coord: { x: number; y: number }, index: number) => ( = ({ fullscreen, size }) => { }} /> ))} - + ) } diff --git a/src/Splash/Splash.tsx b/src/Splash/Splash.tsx index cdc187688..062be8ab8 100644 --- a/src/Splash/Splash.tsx +++ b/src/Splash/Splash.tsx @@ -2,7 +2,6 @@ import * as React from "react" import { readableTextColor } from "../utils" import { expandColor, OperationalStyleConstants } from "../utils/constants" - import styled from "../utils/styled" import Animation from "./Splash.Animation" import OperationalLogo from "./Splash.Logo" @@ -93,7 +92,7 @@ const Static = styled("div")` const Splash: React.FC = ({ color, logo, children, title, actions }) => { return ( - + From e9740d55d6ec8dcb2c12fcd9e91c0ee2657243f5 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:51:06 -0500 Subject: [PATCH 10/22] Use direct lodash import- consistency --- src/useInterval/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 51979eab7..163332761 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -1,4 +1,4 @@ -import { noop } from "lodash" +import noop from "lodash/noop" import { useEffect, useRef } from "react" // From: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ From 5ff8a28dabef727debabaefa3c3a3851196243da Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:51:48 -0500 Subject: [PATCH 11/22] Add details about css trick --- src/Splash/Splash.Animation.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index a9ce982e8..3765286b7 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -35,7 +35,8 @@ const bounce = (coord: number): number => { return coord } -// css Hack so we dont need to worry about max(window.height,window.width) +// css Hack so we dont need to worry about max(window.height,window.width)- Only needed when fullscreen is enabled +// https://spin.atomicobject.com/2015/07/14/css-responsive-square/ const FullScreenWrap = styled("div")({ position: "absolute", width: "100%", @@ -96,7 +97,7 @@ const Animation: React.FC = ({ isFullscreen, size = 600 }) => { 5000, true, ) - + // Only will change if isFullscreen or size changes, a workaround from not having to set outter container width and height to max(window.height,window.width) const Wrap = useCallback( ({ children }) => isFullscreen ? ( From 3fa95de1049010aab4eb06a297986147a3d06197 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Fri, 1 Mar 2019 15:52:44 -0500 Subject: [PATCH 12/22] Add examples :beers: --- src/useInterval/README.md | 106 +++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 6 deletions(-) diff --git a/src/useInterval/README.md b/src/useInterval/README.md index 521f0a1aa..5b3ab85f6 100644 --- a/src/useInterval/README.md +++ b/src/useInterval/README.md @@ -1,18 +1,112 @@ -## Usage +Hook version of setInterval. -This hook sets up an interval and clears it after unmounting +### Referece + +[Making setInterval Declarative with React Hooks](https://overreacted.io/making-setinterval-declarative-with-react-hooks/). + +### Usage + +#### Basic Counter ```jsx -const MyComponent = () => { - let [count, setCount] = React.useState(0) +function BasicCounter() { + const [count, setCount] = useState(0) useInterval(() => { - // Your custom logic here setCount(count + 1) }, 1000) return

{count}

} -; +; +``` + +#### Using two intervals to manipulate the counter + +Example, we can have a delay of one interval be controlled by another: + +```jsx +function Counter() { + const [delay, setDelay] = useState(1000) + const [count, setCount] = useState(0) + + // Increment the counter. + useInterval(() => { + setCount(count + 1) + }, delay) + + // Make it faster every second! + useInterval(() => { + if (delay > 10) { + setDelay(delay / 2) + } + }, 1000) + + function handleReset() { + setDelay(1000) + } + + return ( + <> +

Counter: {count}

+

Delay: {delay}

+ + + ) +} + +; +``` + +#### Immediate argument + +If you need your callback to be delayed for an extended period of time, but you want it to trigger imediatley upon mounting, then pass in immediate. + +```jsx +function MyComp() { + const [inverted, setInvert] = useState(false) + + const [inverted2, setInvert2] = useState(false) + + // Invert colors Immediately + useInterval( + () => { + setInvert(!inverted) + }, + 10000, + true, + ) + + // Invert colors + useInterval(() => { + setInvert2(!inverted2) + }, 10000) + + // Make it faster every second! + + return ( +
+
+

This immediatly gets inverted with navy BG

+
+ +
+

This needs to wait for delay to pass to make Navy

+
+
+ ) +} + +; ``` From 4de2cd4b10b13053726e5a364df332e43fcaa57b Mon Sep 17 00:00:00 2001 From: Mikhail Potomin <639406+mpotomin@users.noreply.github.com> Date: Mon, 4 Mar 2019 11:49:44 -0500 Subject: [PATCH 13/22] code review useInterval/RADME Co-Authored-By: JoshRosenstein <32781407+JoshRosenstein@users.noreply.github.com> --- src/useInterval/README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/useInterval/README.md b/src/useInterval/README.md index 5b3ab85f6..d036f15ab 100644 --- a/src/useInterval/README.md +++ b/src/useInterval/README.md @@ -1,6 +1,6 @@ -Hook version of setInterval. +An implementation of `setInterval` with Hooks. -### Referece +### Reference [Making setInterval Declarative with React Hooks](https://overreacted.io/making-setinterval-declarative-with-react-hooks/). @@ -61,12 +61,11 @@ function Counter() { #### Immediate argument -If you need your callback to be delayed for an extended period of time, but you want it to trigger imediatley upon mounting, then pass in immediate. +If you need your callback to be delayed for an extended period of time, but you want it to trigger immediately upon mounting, then pass in immediate as the third argument. ```jsx function MyComp() { const [inverted, setInvert] = useState(false) - const [inverted2, setInvert2] = useState(false) // Invert colors Immediately @@ -86,14 +85,14 @@ function MyComp() { // Make it faster every second! return ( -
+ <>
-

This immediatly gets inverted with navy BG

+

This immediately gets inverted with a navy background

-

This needs to wait for delay to pass to make Navy

+

This needs to wait for the delay to pass to fire

) From d90a337eca62fa8169e76beb9b72359f48fb9260 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Mon, 4 Mar 2019 11:52:01 -0500 Subject: [PATCH 14/22] Fix Animation Return Logic --- src/Splash/Splash.Animation.tsx | 41 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index 3765286b7..fd25f6e14 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -97,31 +97,24 @@ const Animation: React.FC = ({ isFullscreen, size = 600 }) => { 5000, true, ) - // Only will change if isFullscreen or size changes, a workaround from not having to set outter container width and height to max(window.height,window.width) - const Wrap = useCallback( - ({ children }) => - isFullscreen ? ( - - {children} - - ) : ( - {children} - ), - [isFullscreen, size], - ) - return ( - - {state.coordinates.map((coord: { x: number; y: number }, index: number) => ( - - ))} - + const children = state.coordinates.map((coord: { x: number; y: number }, index: number) => ( + + )) + + // Only will change if isFullscreen or size changes, a workaround from not having to set outter container width and height to max(window.height,window.width) + return isFullscreen ? ( + + {children} + + ) : ( + {children} ) } From 2110fd3ee95258babdac73ad00d8fd49690684c0 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Mon, 4 Mar 2019 12:10:10 -0500 Subject: [PATCH 15/22] Delete comment in useInterval README --- src/useInterval/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/useInterval/README.md b/src/useInterval/README.md index d036f15ab..88f473f6e 100644 --- a/src/useInterval/README.md +++ b/src/useInterval/README.md @@ -82,8 +82,6 @@ function MyComp() { setInvert2(!inverted2) }, 10000) - // Make it faster every second! - return ( <>
Date: Mon, 4 Mar 2019 12:13:48 -0500 Subject: [PATCH 16/22] Update src/useInterval/index.ts Co-Authored-By: JoshRosenstein <32781407+JoshRosenstein@users.noreply.github.com> --- src/useInterval/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 163332761..82a467104 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -11,6 +11,9 @@ export function useInterval(callback: () => void, delay: number | null, immediat // Remember the latest callback. // useEffect has no second argument so it will be executed after each render + // but we don't want to change this value directly in the body of the render function, + // because render should be pure function + // useEffect has no second argument so it will be executed after each render // but we don't want to change this value directly in the body of the render function, // because render should be pure function From b065a4e903a4656fa301c136f0deb719c33e250c Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Mon, 4 Mar 2019 13:48:01 -0500 Subject: [PATCH 17/22] DOH! :angry: --- src/Splash/Splash.Animation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index fd25f6e14..9fde1d722 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState } from "react" +import React, { useState } from "react" import useInterval from "../useInterval" import styled from "../utils/styled" From 8c11741f1319dac4974150c9a4615e30d76fa873 Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Tue, 5 Mar 2019 11:30:25 -0500 Subject: [PATCH 18/22] Add JSDoc to UseInterval --- src/useInterval/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index 82a467104..ddf15a2bf 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -1,17 +1,19 @@ import noop from "lodash/noop" import { useEffect, useRef } from "react" -// From: https://overreacted.io/making-setinterval-declarative-with-react-hooks/ - /** - * Hook version of setInterval. Pass null to the delay to cancel an execution. + * Hook version of setInterval. + * @param {() => void} callback - Callback to be repeatedly excuted over a certain interval. + * @param {number | null} delay - Interval duration in ms. Pass null to cancel an execution. + * @param {boolean} immediate - Pass true to execute the callback immediately upon mounting. + * @see https://overreacted.io/making-setinterval-declarative-with-react-hooks/ */ export function useInterval(callback: () => void, delay: number | null, immediate?: boolean) { const savedCallback = useRef(noop) // Remember the latest callback. // useEffect has no second argument so it will be executed after each render - // but we don't want to change this value directly in the body of the render function, + // but we don't want to change this value directly in the body of the render function, // because render should be pure function // useEffect has no second argument so it will be executed after each render // but we don't want to change this value directly in the body of the render function, From 87c471a070032b532d6669cb586a58dfbb3b37ff Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Wed, 6 Mar 2019 09:28:35 -0500 Subject: [PATCH 19/22] Remove Duplicate Comments --- src/useInterval/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/useInterval/index.ts b/src/useInterval/index.ts index ddf15a2bf..5365b0a36 100644 --- a/src/useInterval/index.ts +++ b/src/useInterval/index.ts @@ -15,9 +15,6 @@ export function useInterval(callback: () => void, delay: number | null, immediat // useEffect has no second argument so it will be executed after each render // but we don't want to change this value directly in the body of the render function, // because render should be pure function - // useEffect has no second argument so it will be executed after each render - // but we don't want to change this value directly in the body of the render function, - // because render should be pure function // After every render, save the latest callback into our ref. useEffect(() => { From 7083527f8a3bc7e1e0a68d5dc003e55cc3df9cc9 Mon Sep 17 00:00:00 2001 From: Tejas Kumar Date: Wed, 6 Mar 2019 23:07:17 -0500 Subject: [PATCH 20/22] Update src/Splash/Splash.Animation.tsx Co-Authored-By: JoshRosenstein <32781407+JoshRosenstein@users.noreply.github.com> --- src/Splash/Splash.Animation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Splash/Splash.Animation.tsx b/src/Splash/Splash.Animation.tsx index 9fde1d722..5ba93588b 100644 --- a/src/Splash/Splash.Animation.tsx +++ b/src/Splash/Splash.Animation.tsx @@ -108,7 +108,7 @@ const Animation: React.FC = ({ isFullscreen, size = 600 }) => { /> )) - // Only will change if isFullscreen or size changes, a workaround from not having to set outter container width and height to max(window.height,window.width) + // Only will change if isFullscreen or size changes, a workaround from not having to set outer container width and height to max(window.height, window.width) return isFullscreen ? ( {children} From 585be4fd7fc59f62c64b9fd3bf06c896c152f1e2 Mon Sep 17 00:00:00 2001 From: Tejas Kumar Date: Wed, 6 Mar 2019 23:07:37 -0500 Subject: [PATCH 21/22] Update src/useInterval/useInterval.test.tsx Co-Authored-By: JoshRosenstein <32781407+JoshRosenstein@users.noreply.github.com> --- src/useInterval/useInterval.test.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/useInterval/useInterval.test.tsx b/src/useInterval/useInterval.test.tsx index ccb3f7f9b..9878537e4 100644 --- a/src/useInterval/useInterval.test.tsx +++ b/src/useInterval/useInterval.test.tsx @@ -4,7 +4,6 @@ import { cleanup, render } from "react-testing-library" import useInterval, { useInterval as namedHook } from "." // ref https://github.com/Hermanya/use-interval/blob/master/src/test.tsx - beforeEach(cleanup) const MyComponent: React.FC<{ fn: () => void; delay: number | null; immediate?: boolean }> = ({ From 32c5741c5dac6c4c713000392680ae5b5deb3b2e Mon Sep 17 00:00:00 2001 From: Josh Rosenstein <32781407+JoshRosenstein@users.noreply.github.com> Date: Thu, 7 Mar 2019 20:03:04 -0500 Subject: [PATCH 22/22] Fix useInterval & and add a button to toggle the counter --- src/useInterval/README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/useInterval/README.md b/src/useInterval/README.md index 88f473f6e..aca8970b9 100644 --- a/src/useInterval/README.md +++ b/src/useInterval/README.md @@ -10,7 +10,7 @@ An implementation of `setInterval` with Hooks. ```jsx function BasicCounter() { - const [count, setCount] = useState(0) + const [count, setCount] = React.useState(0) useInterval(() => { setCount(count + 1) @@ -28,17 +28,20 @@ Example, we can have a delay of one interval be controlled by another: ```jsx function Counter() { - const [delay, setDelay] = useState(1000) - const [count, setCount] = useState(0) + const [start, setStart] = React.useState(false) + const [delay, setDelay] = React.useState(1000) + const [count, setCount] = React.useState(0) // Increment the counter. useInterval(() => { - setCount(count + 1) + if (start) { + setCount(count + 1) + } }, delay) // Make it faster every second! useInterval(() => { - if (delay > 10) { + if (delay > 10 && start) { setDelay(delay / 2) } }, 1000) @@ -49,6 +52,7 @@ function Counter() { return ( <> +

Counter: {count}

Delay: {delay}

@@ -65,8 +69,8 @@ If you need your callback to be delayed for an extended period of time, but you ```jsx function MyComp() { - const [inverted, setInvert] = useState(false) - const [inverted2, setInvert2] = useState(false) + const [inverted, setInvert] = React.useState(false) + const [inverted2, setInvert2] = React.useState(false) // Invert colors Immediately useInterval( @@ -83,7 +87,7 @@ function MyComp() { }, 10000) return ( - <> +