Skip to content

feat: add onAnimationFrame lifecycle function #14594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

Conversation

Rich-Harris
Copy link
Member

Just an idle thought I had while washing the dishes: should we have an onFrame function? It would mean for example that this demo could be written like this:

$effect(() => {
  const context = canvas.getContext('2d');

  onFrame(() => {
    paint(context, Date.now());
  });
});

Alternatively we might want to have some sort of reactive time primitive (other than SvelteDate) so that it could be used in deriveds too. Either way not wedded to it, just an idle thought that I thought was worth a PR

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

Copy link

changeset-bot bot commented Dec 6, 2024

🦋 Changeset detected

Latest commit: 605a1f7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Rich-Harris
Copy link
Member Author

preview: https://svelte-dev-git-preview-svelte-14594-svelte.vercel.app/

this is an automated message

Copy link
Contributor

github-actions bot commented Dec 6, 2024

Playground

pnpm add https://pkg.pr.new/svelte@14594

1 similar comment
Copy link
Contributor

github-actions bot commented Dec 6, 2024

Playground

pnpm add https://pkg.pr.new/svelte@14594

@dummdidumm
Copy link
Member

While it's nice, this does feel more of a thing for a utility or animation library. I wouldn't call it a lifecycle function at least and expose it through svelte/reactivity instead.

@ottomated
Copy link
Contributor

Adjacent to #12441

@trueadm
Copy link
Contributor

trueadm commented Dec 12, 2024

Adjacent to #12441

I'm not sure it is at all. You definitely don't want to be updating the UI with Date.now() every frame, that's going to put a lot of pressure on the runtime for no real benefit. I'd imagine you'd only want to update the time in relation to your UI requirements, such as every second or minute. This is very much a user-space problem rather than a problem that Svelte should even attempt to solve.

@Rich-Harris Rich-Harris changed the title feat: add onFrame lifecycle function feat: add onAnimationFrame lifecycle function Apr 12, 2025
@svelte-docs-bot
Copy link

@Rich-Harris
Copy link
Member Author

Renamed to onAnimationFrame. I toyed with putting it in svelte/reactivity or svelte/motion but neither felt right — I think you can make the case that it is a lifecycle function, and it definitely feels more natural to me to have it alongside onMount than elsewhere

@dummdidumm
Copy link
Member

FWIW I still think this is not worth adding as it's so easy to replicate in user land - so if this is about cleaning the PR queue I'd rather close it.

@Rich-Harris
Copy link
Member Author

It's easy but annoying — you have to understand whether it's 'safe' to run the logic inside a requestAnimationFrame callback the first time or if it'll result in flicker unless you call it directly inside the effect, in which case you might need to faff about with untrack unless you're using onMount (you don't need to, because it is safe, but that means you have to call requestAnimationFrame twice — once inside the callback, once to kick it off). And of course it's a lot more verbose — this...

$effect(() => {
  let frame = requestAnimationFrame(function next() {
    frame = requestAnimationFrame(next);
    do_stuff();
  });

  return () => {
    cancelAnimationFrame(frame);
  };
});

...versus this:

import { onAnimationFrame } from 'svelte';

onAnimationFrame(() => {
  do_stuff();
});

The intent-to-noise ratio is much higher in the second case. It's something I've wanted often enough that I do think its presence is justified, it's not just about cleaning the PR queue.

@dummdidumm
Copy link
Member

I'm not saying it doesn't have any value, but not that it deserves to be in the same place as things like "real" life cycle hooks or other important stuff under the svelte import space. It feels like something that can be put into a 3rd party lib like runed

@TGlide
Copy link
Member

TGlide commented May 20, 2025

I'm not saying it doesn't have any value, but not that it deserves to be in the same place as things like "real" life cycle hooks or other important stuff under the svelte import space. It feels like something that can be put into a 3rd party lib like runed

We have something similar in runed :) https://www.runed.dev/docs/utilities/animation-frames

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants