I'm exploring a hook that generates a wrapper component to reduce the boilerplate of adding animations to my react-native app. I already wrote a hook that returns animated values and takes care of managing them internally, it works great. Each time I use it however, I have to write the boilerplate of applying the animated values like so:
//pseudocode
const [animatedValue, animationRef, ...otherUsefuLStuff] = useMyGenericAnimationHook(...some animation config)
return (
<Animated.View style={{transform: [{translateY: animatedValue}]}}>
.....
</Animated.View>
)
This isn't a big deal, but it's still some boilerplate I have to put in for each animation. I was considering if I could return a wrapper component from my animation hook to abstract away this boilerplate, something like the following
//pseudocode
const [AnimatedTranslateY, animatedValue, animationRef, ...otherUsefulStuff] = useMyGenericAnimationHook(... some animation config)
return (
<AnimatedTranslateY>.....</AnimatedTranslateY>
)
This looks cleaner, but returning a new component type from a hook definitely causes a problem. React will tear down and rebuild the children on each render because each time useMyAnimationHook() runs it will return a new component type!
My initial idea is to memoize the returned component type like so inside my hook
//pseudocode
const useMyGenericAnimationHook= (....configuration arguments) => {
const animatedValueRef = ....create the animated value(s) ref(s)
const WrapperView: React.FC<ViewProps> = useMemo(
() =>
React.memo(({ children, style, ...restProps }) => (
<Animated.View {...restProps}
style={[style, { transform: ...apply animated value(s)}]}>
{children}
</Animated.View>
)),
[animatedValueRef.current]
)
return [WrapperView, animationHandle, otherUsefulStuff]
}
Here's where I'm somewhat confused. I think that this should work fine and not rebuild the tree on each render. The component type should remain stable unless the dependencies given to useMemo change at which point we want it to render anyway. I'm not totally confident about this however.
What will react's behavior be when using <WrapperView>?
Is there any reason why this isn't a good pattern?
Thanks for any insight!