Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tasty-kangaroos-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': minor
---

feat: add `onFrame` lifecycle function
26 changes: 26 additions & 0 deletions packages/svelte/src/index-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,32 @@ export function afterUpdate(fn) {
init_update_callbacks(component_context).a.push(fn);
}

/**
* The `onFrame` function schedules a callback to run on `requestAnimationFrame`. It must be called inside an effect (e.g. during component initialisation).
*
* `onFrame` does not run inside [server-side components](https://svelte.dev/docs/svelte/svelte-server#render).
*
* @template T
* @param {() => NotFunction<T> | Promise<NotFunction<T>> | (() => any)} fn
* @returns {void}
*/
export function onFrame(fn) {
onMount(() => {
let frame = -1;

function next() {
frame = requestAnimationFrame(next);
fn();
}

next();

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

/**
* Legacy-mode: Init callbacks object for onMount/beforeUpdate/afterUpdate
* @param {ComponentContext} context
Expand Down
1 change: 1 addition & 0 deletions packages/svelte/src/index-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export function onDestroy(fn) {
export {
noop as beforeUpdate,
noop as afterUpdate,
noop as onFrame,
noop as onMount,
noop as flushSync,
run as untrack
Expand Down
8 changes: 8 additions & 0 deletions packages/svelte/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,13 @@ declare module 'svelte' {
* @deprecated Use [`$effect`](https://svelte.dev/docs/svelte/$effect) instead
* */
export function afterUpdate(fn: () => void): void;
/**
* The `onFrame` function schedules a callback to run on `requestAnimationFrame`. It must be called inside an effect (e.g. during component initialisation).
*
* `onFrame` does not run inside [server-side components](https://svelte.dev/docs/svelte/svelte-server#render).
*
* */
export function onFrame<T>(fn: () => NotFunction<T> | Promise<NotFunction<T>> | (() => any)): void;
/**
* Synchronously flushes any pending state changes and those that result from it.
* */
Expand Down Expand Up @@ -1671,6 +1678,7 @@ declare module 'svelte/motion' {
* <input type="range" bind:value={spring.target} />
* <input type="range" bind:value={spring.current} disabled />
* ```
* @since 5.8.0
*/
export class Spring<T> {
constructor(value: T, options?: SpringOpts);
Expand Down
Loading