maxd
maxd

Reputation: 11

Recoil.js Strange behavior when using recoilState for controlling animationFrame

import React, { useState, useLayoutEffect } from "react";
import { useRecoilState, atom } from "recoil";

function Counter() {
  const [counter, setCounter] = useState(0);
  //const [isPaused, setIsPaused] = useState(true);
  const [running, setRunning] = useRecoilState(isRunning);

  useLayoutEffect(() => {
    if (running) {
      let timerId;

      const f = () => {
        setCounter((x) => x + 1);
        timerId = requestAnimationFrame(f);
      };

      timerId = requestAnimationFrame(f);

      return () => cancelAnimationFrame(timerId);
    }
  }, [running]);

  return (
    <p>
      Counter: {counter} ...{" "}
      <button onClick={() => setRunning(!running)}>
        {!running ? "Resume" : "Pause"}
      </button>
    </p>
  );
}

export default Counter;

const isRunning = atom({
  key: "isRunning",
  default: false
});

https://codesandbox.io/s/heuristic-moon-8l3g6?file=/src/App.js

The toggle button in demo above will work to pause/resume the counter for a few times, then it will suddenly stop functioning and the animationFrame will never cease. If I were to comment out useRecoilState and uncomment useState, it works as expected again. Does this have to do with recoil introducing latency when fetching the value?

Upvotes: 1

Views: 82

Answers (0)

Related Questions