Why does my sprite animation sometimes skip frames after a state update?

Yo Kirupa folks, I’m wiring up a tiny pixel-art character preview in a React-ish UI and I’m trying to keep the animation smooth while state updates happen. Every once in a while it jumps a frame or stutters, and I’m worried I’m mixing DOM reads/writes and shared refs in a dumb way.

let frame = 0;
let last = performance.now();
const frames = 8;
const fps = 12;
const state = { playing: true };

function tick(now) {
  const dt = now - last;
  if (state.playing && dt >= 1000 / fps) {
    frame = (frame + Math.floor(dt / (1000 / fps))) % frames;
    last = now;
    el.style.backgroundPositionX = `${-frame * 32}px`;
    el.dataset.frame = frame; // UI reads this elsewhere
  }
  requestAnimationFrame(tick);
}
requestAnimationFrame(tick);

If the UI reads dataset.frame and triggers a re-render sometimes, what’s a good pattern to avoid animation drift and random frame skips without bloating the architecture?

VaultBoy

yeah, the skip is probably from last = now nuking the leftover time after a slow render. so when React hiccups, you catch up by jumping frames, but the timing gets a little weird after that.

i’d keep a tiny accumulator and only subtract whole frame steps, like acc -= step in a loop. and i wouldn’t use dataset.frame as the thing React reads from — keep frame in a ref or some tiny store and let the UI subscribe to that instead.