Skip to main content
Version: 3.x


This hook allows you to run a piece of code on every frame update.

useFrameCallback(callback: (frameInfo: FrameInfo) => void, autostart = true): [FrameCallback]


callback [Function]

A single worklet function that will be called on every frame update. This function receives a FrameInfo object as an argument.

autostart [boolean]

Optional boolean that specifies if the callback should start running when registration is complete. This argument defaults to true.


An object of type FrameCallback which allows you to read and control the callback state.


FrameCallback: [object]


  • setActive: (isActive: boolean) => void: begins / stops listening for frame updates
  • isActive: boolean: indicates whether the callback is active (true) or not (false)
  • callbackId: number: a unique identifier of the callback function

FrameInfo: [object]


  • timestamp: number: the system time (in milliseconds) when the last frame was rendered
  • timeSincePreviousFrame: number | null: time (in milliseconds) since last frame. This value will be null on the first frame after activation. Starting from the second frame, it should be ~16 ms on 60 Hz or ~8 ms on 120 Hz displays (when there is no lag)
  • timeSinceFirstFrame: number: time (in milliseconds) since the callback was last activated


import Animated, {
} from 'react-native-reanimated';
import {Button, View} from 'react-native';

import React from 'react';

export default function FrameCallbackExample() {
const x = useSharedValue(0);

const frameCallback = useFrameCallback((frameInfo) => {
if (frameInfo.timeSincePreviousFrame === null) {
console.log('First frame!');
} else {
console.log(`${frameInfo.duration} ms have passed since the previous frame`);
// Move the box by one pixel on every frame
x.value += 1;
}, false);

const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
translateX: x.value,

return (
<Animated.View style={[, animatedStyle1]} />
<Button title={'Start/stop'} onPress={() => frameCallback.setActive(!frameCallback.isActive)}>