Skip to content

Instantly share code, notes, and snippets.

@Nodonisko
Created October 21, 2025 18:42
Show Gist options
  • Select an option

  • Save Nodonisko/e43178790a9ea3b00cca4bfca1babb1d to your computer and use it in GitHub Desktop.

Select an option

Save Nodonisko/e43178790a9ea3b00cca4bfca1babb1d to your computer and use it in GitHub Desktop.
import React, { useEffect } from 'react';
import { Dimensions, StyleSheet, TextInput, View, Text } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
interpolateColor,
setNativeProps,
useAnimatedRef,
useAnimatedStyle,
useFrameCallback,
useSharedValue,
withSpring,
} from 'react-native-reanimated';
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
export const ReanimatedFpsCounter = React.memo(() => {
const heartbeats = useSharedValue<number[]>(
// Predefine array with 5s of heartbeats
new Array(300).fill(Date.now() - 1000),
);
const fps = useSharedValue<number>(0);
const ref = useAnimatedRef<TextInput>();
const lastUpdateTime = useSharedValue<number>(Date.now());
useEffect(() => {
let rafId: number;
const tick = () => {
heartbeats.set(value => {
value.shift();
value.push(Date.now());
return value;
});
rafId = requestAnimationFrame(tick);
};
rafId = requestAnimationFrame(tick);
return () => cancelAnimationFrame(rafId);
}, []);
useFrameCallback(() => {
const now = Date.now();
if (now - lastUpdateTime.value < 300) {
return;
}
const heartbeatsArray = heartbeats.get();
// Count heartbeats in the last 1 second
const oneSecondAgo = now - 1000;
let recentHeartbeats = 0;
// Count the number of heartbeats in the last second, but start from end so we save resources
for (let i = heartbeatsArray.length - 1; i >= 0; i--) {
if (heartbeatsArray[i] >= oneSecondAgo) {
recentHeartbeats++;
} else {
break;
}
}
lastUpdateTime.value = now;
fps.value = recentHeartbeats;
setNativeProps(ref, { text: recentHeartbeats.toString() });
});
const style = useAnimatedStyle(() => {
return {
backgroundColor: interpolateColor(fps.value, [0, 60], ['red', 'green']),
};
});
return (
<AnimatedTextInput
style={[
style,
{
color: 'white',
fontSize: 16,
},
]}
textAlign="center"
textAlignVertical="center"
ref={ref}
editable={false}
underlineColorAndroid="transparent"
/>
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment