-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseSpring.ts
45 lines (38 loc) Β· 1.2 KB
/
useSpring.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import { useEffect, useMemo, useState } from 'react';
import { Spring, SpringSystem } from 'rebound';
const useSpring = (targetValue: number = 0, tension: number = 50, friction: number = 3) => {
const [spring, setSpring] = useState<Spring | null>(null);
const [value, setValue] = useState<number>(targetValue);
// memoize listener to being able to unsubscribe later properly, otherwise
// listener fn will be different on each re-render and wouldn't unsubscribe properly.
const listener = useMemo(
() => ({
onSpringUpdate: (currentSpring) => {
const newValue = currentSpring.getCurrentValue();
setValue(newValue);
},
}),
[]
);
useEffect(() => {
if (!spring) {
const newSpring = new SpringSystem().createSpring(tension, friction);
newSpring.setCurrentValue(targetValue);
setSpring(newSpring);
newSpring.addListener(listener);
}
return () => {
if (spring) {
spring.removeListener(listener);
setSpring(null);
}
};
}, [tension, friction, spring]);
useEffect(() => {
if (spring) {
spring.setEndValue(targetValue);
}
}, [targetValue]);
return value;
};
export default useSpring;