Skip to content

Instantly share code, notes, and snippets.

@ecklf
Last active September 7, 2021 09:24
Show Gist options
  • Save ecklf/c5137cb9c7ea9af3ca9bd25c6efb20ca to your computer and use it in GitHub Desktop.
Save ecklf/c5137cb9c7ea9af3ca9bd25c6efb20ca to your computer and use it in GitHub Desktop.

Revisions

  1. ecklf renamed this gist Sep 7, 2021. 1 changed file with 0 additions and 0 deletions.
  2. ecklf created this gist Sep 7, 2021.
    71 changes: 71 additions & 0 deletions Trigger an event after holding down an element for a duration
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,71 @@
    // Usage:
    // const Button = () => {
    // const { completion, ...bind } = useTimedEvent(() => { fire(); }, { duration: 1000 });
    // return <button {...bind}>Button</button>;
    // };

    import { useEffect, useRef, useState } from "react";

    const useTimedEvent = (
    callback: (() => void) | (() => Promise<void>),
    options?: { refreshRate?: number; duration?: number }
    ) => {
    const timerId = useRef<any>(null);
    const [progress, setProgress] = useState(0);

    const refreshRate = options?.refreshRate ?? 10;
    const triggerAt = (options?.duration ?? 1000) / refreshRate;
    const completion = (progress / triggerAt) * 100;

    useEffect(() => () => clearInterval(timerId.current), []);

    useEffect(() => {
    if (progress === triggerAt) {
    endProgress();
    callback();
    }
    }, [progress, triggerAt, callback]);

    const startProgress = () => {
    timerId.current = setInterval(
    () => setProgress((val) => val + 1),
    refreshRate
    );
    };

    const endProgress = () => {
    setProgress(0);
    clearInterval(timerId.current);
    };

    const onMouseDown = () => {
    startProgress();
    };

    const onTouchStart = () => {
    startProgress();
    };

    const onMouseUp = () => {
    endProgress();
    };

    const onMouseOut = () => {
    endProgress();
    };

    const onTouchEnd = () => {
    endProgress();
    };

    return {
    completion,
    onMouseDown,
    onTouchStart,
    onMouseUp,
    onMouseOut,
    onTouchEnd,
    };
    };

    export default useTimedEvent;