Skip to content

Commit 98e1410

Browse files
authored
perf: use a single heartbeat connection for all useMotion hooks (#21)
* fix(use-async-effect): unknown -> any * perf: use a single heartbeat connection for all `useMotion` hooks
1 parent e47ffc6 commit 98e1410

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

src/use-motion/use-motion.ts

+37-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,33 @@
11
import type { Binding } from "@rbxts/react";
2-
import { useBinding, useMemo } from "@rbxts/react";
2+
import { useBinding, useEffect, useMemo } from "@rbxts/react";
33
import type { Motion, MotionGoal } from "@rbxts/ripple";
44
import { createMotion } from "@rbxts/ripple";
5-
import { useEventListener } from "../use-event-listener";
65
import { RunService } from "@rbxts/services";
76

7+
const callbacks = new Set<(dt: number) => void>();
8+
let connection: RBXScriptConnection | undefined;
9+
10+
function connect(callback: (dt: number) => void) {
11+
callbacks.add(callback);
12+
13+
if (!connection) {
14+
connection = RunService.Heartbeat.Connect((dt) => {
15+
for (const callback of callbacks) {
16+
callback(dt);
17+
}
18+
});
19+
}
20+
}
21+
22+
function disconnect(callback: (dt: number) => void) {
23+
callbacks.delete(callback);
24+
25+
if (callbacks.isEmpty()) {
26+
connection?.Disconnect();
27+
connection = undefined;
28+
}
29+
}
30+
831
export function useMotion(initialValue: number): LuaTuple<[Binding<number>, Motion]>;
932
export function useMotion<T extends MotionGoal>(initialValue: T): LuaTuple<[Binding<T>, Motion<T>]>;
1033
export function useMotion<T extends MotionGoal>(initialValue: T) {
@@ -14,13 +37,19 @@ export function useMotion<T extends MotionGoal>(initialValue: T) {
1437

1538
const [binding, setValue] = useBinding(initialValue);
1639

17-
useEventListener(RunService.Heartbeat, (delta) => {
18-
const value = motion.step(delta);
40+
useEffect(() => {
41+
const callback = (delta: number) => {
42+
const value = motion.step(delta);
43+
44+
if (value !== binding.getValue()) {
45+
setValue(value);
46+
}
47+
};
1948

20-
if (value !== binding.getValue()) {
21-
setValue(value);
22-
}
23-
});
49+
connect(callback);
50+
51+
return () => disconnect(callback);
52+
}, []);
2453

2554
return $tuple(binding, motion);
2655
}

0 commit comments

Comments
 (0)