编辑:注意 - 可能会导致严重的性能问题。我一直无法弄清楚原因,但是如果您将它用于 30 多个同步动画,您的帧速率将慢到爬行。似乎它必须是 Animated.Value addListener 的 react-native 中的一个错误,因为我没有发现我的代码有任何问题,它只设置了一个侦听器,该侦听器设置了一个应该是即时的 ref。
这是我想出的一个钩子,不需要访问私有内部值就可以做到这一点。
/**
* Since there's no (official) way to read an Animated.Value synchronously this is the best solution I could come up with
* to have access to an up-to-date copy of the latest value without sacrificing performance.
*
* @param animatedValue the Animated.Value to track
* @param initial Optional initial value if you know it to initialize the latest value ref before the animated value listener fires for the first time
*
* returns a ref with the latest value of the Animated.Value and a boolean ref indicating if a value has been received yet
*/
const useAnimatedLatestValueRef = (animatedValue: Animated.Value, initial?: number) => {
//If we're given an initial value then we can pretend we've received a value from the listener already
const latestValueRef = useRef(initial ?? 0)
const initialized = useRef(typeof initial == "number")
useEffect(() => {
const id = animatedValue.addListener((v) => {
//Store the latest animated value
latestValueRef.current = v.value
//Indicate that we've recieved a value
initialized.current = true
})
//Return a deregister function to clean up
return () => animatedValue.removeListener(id)
//Note that the behavior here isn't 100% correct if the animatedValue changes -- the returned ref
//may refer to the previous animatedValue's latest value until the new listener returns a value
}, [animatedValue])
return [latestValueRef, initialized] as const
}