import React, { useRef, useState, useEffect } from 'react'; type Timestamp = number; type Milliseconds = number; /** * usage: const [canvasRef] = useRedrawer(props, drawFn, 100, [props]) * or with more restricted props to pass to the draw function and/or to use * as dependencies for the useEffect hook. */ export function useRedrawer( props: TProps, // is this necessary ??? drawFn: (ctx: CanvasRenderingContext2D, props: TProps) => void, maximumDrawInterval: Milliseconds, deps?: React.DependencyList, ): [React.MutableRefObject] { const canvasRef = useRef(); const [lastDraw, setLastDraw] = useState(); const [timerRunning, setTimerRunning] = useState(false); const timer = useRef(); useEffect(() => { function redraw() { setLastDraw(Date.now()); const ctx = canvasRef.current.getContext('2d'); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); drawFn(ctx, props); } if (timerRunning) { clearTimeout(timer.current); setTimerRunning(false); } if (!canvasRef.current) return; if (lastDraw < Date.now() - maximumDrawInterval) { redraw(); } else { timer.current = setTimeout(redraw, maximumDrawInterval - (Date.now() - lastDraw)); setTimerRunning(true); } }, deps); return [canvasRef]; }