-
Notifications
You must be signed in to change notification settings - Fork 2
Add react utils hook useInterval #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
a8bb256
3fc199e
bd47942
ff74945
b345ced
e60598e
0ae1edd
3ba1f8a
ae2af9c
8ef6d64
3ad77c1
c95e99c
4fa85f0
83b67a6
ac3da6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| import React from "react"; | ||
| import { useInterval } from "../../src/lib/hooks/useInterval"; | ||
|
|
||
| interface TestComponentProps { | ||
| callbackFunction: () => void | Promise<void>; | ||
| intervalValue: number; | ||
| autoStart: boolean; | ||
| } | ||
|
|
||
| function TestComponent({ callbackFunction, intervalValue, autoStart }: TestComponentProps) { | ||
| const result = useInterval({ callback: callbackFunction, interval: intervalValue, autoStart: autoStart }); | ||
| return ( | ||
| <> | ||
| <div data-testid="test-component"> | ||
| Component using useInterval hook | ||
| <button onClick={result.startInterval}>Start interval</button> | ||
| <button onClick={result.stopInterval}>Stop interval</button> | ||
| </div> | ||
| </> | ||
| ); | ||
| } | ||
|
|
||
| describe("useInterval Hook - Cypress Component Tests", () => { | ||
| it("Component mounts", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("Hello World!"); | ||
| }) | ||
| .as("componentMountSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={false} />); | ||
|
|
||
| cy.get('[data-testid="test-component"]').should("be.visible"); | ||
| cy.get('[data-testid="test-component"]').should("contain.text", "Component using useInterval hook"); | ||
| }); | ||
|
|
||
| it("should not start to poll when autostart is set on false", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("Does not start the interval automaticly"); | ||
| }) | ||
| .as("callbackSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={false} />); | ||
| cy.wait(3000); | ||
| cy.get("@callbackSpy").should("not.have.been.called"); | ||
| }); | ||
|
|
||
| it("should remain stopped until start is called when autostart is false", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("Does not start the interval automaticly"); | ||
| }) | ||
| .as("callbackSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={false} />); | ||
| cy.wait(3000); | ||
| cy.get("@callbackSpy").should("not.have.been.called"); | ||
| cy.contains("button", "Start interval").click(); | ||
| cy.wait(1000); | ||
| cy.contains("button", "Stop interval").click(); | ||
| cy.get("@callbackSpy").should("have.been.calledOnce"); | ||
| }); | ||
|
|
||
| it("should start to poll automatically when autostart is true", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("The interval runs automatically when autostart is true."); | ||
| }) | ||
| .as("callbackSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={true} />); | ||
| cy.wait(3000); | ||
| cy.get("@callbackSpy").should("have.been.calledThrice"); | ||
| }); | ||
|
|
||
| it("should poll continuously until stopped when autostart is true", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("The interval runs automatically until it gets stopped."); | ||
| }) | ||
| .as("callbackSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={true} />); | ||
| cy.wait(1000); | ||
| cy.get("@callbackSpy").should("have.been.calledOnce"); | ||
| cy.contains("button", "Stop interval").click(); | ||
| cy.get("@callbackSpy").should("have.been.calledOnce"); | ||
| }); | ||
|
|
||
| it("should only be possible to start the interval once", () => { | ||
| const callbackSpy = cy | ||
| .spy(() => { | ||
| console.log("The interval can only be started once."); | ||
| }) | ||
| .as("callbackSpy"); | ||
|
|
||
| cy.mount(<TestComponent callbackFunction={callbackSpy} intervalValue={1000} autoStart={false} />); | ||
|
|
||
| cy.contains("button", "Start interval").click(); | ||
| cy.contains("button", "Start interval").click(); | ||
|
|
||
| cy.get("@callbackSpy").should("have.been.calledOnce"); | ||
| cy.wait(1000); | ||
| cy.contains("button", "Stop interval").click(); | ||
| cy.get("@callbackSpy").should("have.been.calledTwice"); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,84 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useRef, useCallback, useState, useEffect } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The interface for the polling properties | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface UseIntervalProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The callback function | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callback: () => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The interval of the polling function | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
dom-baur marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interval: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The boolean to set if the hook is initially polling or not | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
dom-baur marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| autoStart: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The interface for the polling result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface UseIntervalResult { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The current state of the hook wheter it's polling or not | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
neoscie marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isRunning: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The function to start polling | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startInterval: () => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The function to stopp polling | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
neoscie marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stopInterval(): void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
dom-baur marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * The useInterval hook | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param props The props for the useInterval hook, see {@link UseIntervalProps} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @returns The result of the useInterval, see {@link UseIntervalResult} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const useInterval = (props: UseIntervalProps): UseIntervalResult => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { autoStart, callback, interval } = props; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isRunning, setIsRunning] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const intervalRef = useRef<number | null>(null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const callbackRef = useRef<() => void>(callback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const startInterval = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsRunning((prevIsRunning) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!prevIsRunning && (!intervalRef.current || intervalRef.current === -1)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Starting interval"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
neoscie marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intervalRef.current = window.setInterval(callbackRef.current, interval); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [interval]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const stopInterval = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsRunning(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| window.clearInterval(intervalRef.current || -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| intervalRef.current = -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callbackRef.current = callback; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Starting interval", isRunning); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
dom-baur marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isRunning) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| startInterval(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return stopInterval; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [callback, isRunning, interval, startInterval, stopInterval]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Starting interval", isRunning); | |
| if (isRunning) { | |
| startInterval(); | |
| } | |
| return stopInterval; | |
| }, [callback, isRunning, interval, startInterval, stopInterval]); | |
| if (isRunning) { | |
| if (!intervalRef.current || intervalRef.current === -1) { | |
| intervalRef.current = window.setInterval(() => { | |
| callbackRef.current(); | |
| }, interval); | |
| } | |
| } else { | |
| if (intervalRef.current && intervalRef.current !== -1) { | |
| window.clearInterval(intervalRef.current); | |
| intervalRef.current = -1; | |
| } | |
| } | |
| return () => { | |
| if (intervalRef.current && intervalRef.current !== -1) { | |
| window.clearInterval(intervalRef.current); | |
| intervalRef.current = -1; | |
| } | |
| }; | |
| }, [callback, isRunning, interval]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@neotrow is this accurate?
Uh oh!
There was an error while loading. Please reload this page.