Kocur4d
Kocur4d

Reputation: 6931

requestAnimationFrame callback is not being called while using with React

I am trying to wrap canvas component with the react component and setup requestAnimationFrame to be able to draw animations on canvas.

I have a simple component that tries to simply draw a circle:

import * as React from "react";
import { useLayoutEffect, useRef } from "react";

export interface Props {}

export const Loop: React.FC<Props> = () => {
  const cv = useRef<HTMLCanvasElement>(null);
  const oldTimestamp = useRef<number>(0);

  useLayoutEffect(() => {
    let animationID = 0;

    console.log("USEEFFECT");

    const loop = (timestamp: number) => {
      let secondsPassed = (timestamp - oldTimestamp.current) / 1000;
      secondsPassed = Math.min(secondsPassed, 0.1);

      oldTimestamp.current = timestamp;

      console.log("LOOP");

      update(secondsPassed);
      draw();

      animationID = requestAnimationFrame(loop);
    };

    animationID = requestAnimationFrame(loop);

    return cancelAnimationFrame(animationID);
  }, []);

  const update = (secondsPassed: number) => {};

  const draw = () => {
    console.log("DRAW");
    const ctx = cv && cv.current && cv.current.getContext("2d");
    if (ctx) {
      ctx.beginPath();
      ctx.arc(100, 75, 50, 0, 2 * Math.PI);
      ctx.stroke();
    }
  };

  return (
    <div>
      <canvas ref={cv}></canvas>
    </div>
  );
};

I have added three console.log calls to help identified what is going on. ATM only the console.log("USEEFFECT"); is being logged but nothing else. It looks to me that the animationID = requestAnimationFrame(loop); in the useLayoutEffect is not calling the loop callback.

I think that the requestAnimationFrame setup in the useLayoutEffect is correct.

What I am doing wrong?

Upvotes: 0

Views: 747

Answers (1)

You cancel animation frame immediately, instead you should return function:

return () => cancelAnimationFrame(animationID)

Upvotes: 2

Related Questions