react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
89 lines (85 loc) • 3.05 kB
JavaScript
'use strict';
import { useRef, useState } from 'react';
import { createSerializable, serializableMappingCache } from 'react-native-worklets';
import { SHOULD_BE_USE_WEB } from '../common/constants';
import { getShadowNodeWrapperFromRef } from '../fabricUtils';
import { makeMutable } from '../mutables';
import { findNodeHandle } from '../platformFunctions/findNodeHandle';
function useAnimatedRefBase(getWrapper) {
const observers = useRef(new Map()).current;
const wrapperRef = useRef(null);
const resultRef = useRef(null);
if (!resultRef.current) {
const fun = ref => {
if (ref) {
wrapperRef.current = getWrapper(ref);
// We have to unwrap the tag from the shadow node wrapper.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fun.getTag = () => findNodeHandle(ref);
fun.current = ref;
if (observers.size) {
const currentTag = fun?.getTag?.() ?? null;
observers.forEach((cleanup, observer) => {
// Perform the cleanup before calling the observer again.
// This ensures that all events that were set up in the observer
// are cleaned up before the observer sets up new events during
// the next call.
cleanup?.();
observers.set(observer, observer(currentTag));
});
}
}
return wrapperRef.current;
};
fun.observe = observer => {
// Call observer immediately to get the initial value
const cleanup = observer(fun?.getTag?.() ?? null);
observers.set(observer, cleanup);
return () => {
observers.get(observer)?.();
observers.delete(observer);
};
};
fun.current = null;
resultRef.current = fun;
}
return resultRef.current;
}
function useAnimatedRefNative() {
const [sharedWrapper] = useState(() => makeMutable(null));
const resultRef = useAnimatedRefBase(ref => {
const currentWrapper = getShadowNodeWrapperFromRef(ref);
sharedWrapper.value = currentWrapper;
return currentWrapper;
});
if (!serializableMappingCache.get(resultRef)) {
const animatedRefSerializableHandle = createSerializable({
__init: () => {
'worklet';
return () => sharedWrapper.value;
}
});
serializableMappingCache.set(resultRef, animatedRefSerializableHandle);
}
return resultRef;
}
function useAnimatedRefWeb() {
return useAnimatedRefBase(ref => {
if (ref.getScrollableNode) {
return ref.getScrollableNode();
}
if (ref.getNativeScrollRef) {
return ref.getNativeScrollRef();
}
return ref;
});
}
/**
* Lets you get a reference of a view that you can use inside a worklet.
*
* @returns An object with a `.current` property which contains an instance of
* the reference object.
* @see https://docs.swmansion.com/react-native-reanimated/docs/core/useAnimatedRef
*/
export const useAnimatedRef = SHOULD_BE_USE_WEB ? useAnimatedRefWeb : useAnimatedRefNative;
//# sourceMappingURL=useAnimatedRef.js.map