@umituz/react-native-animation
v2.2.0
Published
Centralized animation utilities and components for @umituz ecosystem
Readme
@umituz/react-native-animation
Performance-optimized animation utilities and components for React Native applications with react-native-reanimated.
Note: This package provides general-purpose animation utilities only. Domain-specific animations (like wheel spinners, etc.) should be implemented in their respective application domains.
Features
- 🚀 Performance Optimized - Memory leak prevention, worklet optimizations
- 🃏 Animated Card - Card animations with randomized entry directions
- 🎨 Reanimated Re-exports - All react-native-reanimated utilities available
- 🔧 TypeScript First - Full TypeScript support with comprehensive types
- 📱 React 18+ Ready - Concurrency support and proper cleanup
- ♿ Accessibility - Support for reduced motion preferences
Installation
npm install @umituz/react-native-animation react-native-reanimated
# or
yarn add @umituz/react-native-animation react-native-reanimatedQuick Start
Animated Card
Optimized card component with automatic cleanup and memory leak prevention.
import { AnimatedCard } from '@umituz/react-native-animation';
function MyScreen() {
const [visible, setVisible] = useState(true);
return (
<AnimatedCard
visible={visible}
onAnimationEnd={() => console.log('Animation complete')}
disabled={false} // Set to true to disable animations
>
<Text>Hello, World!</Text>
</AnimatedCard>
);
}Using Reanimated Utilities
All react-native-reanimated utilities are re-exported for convenience:
import {
useSharedValue,
useAnimatedStyle,
withTiming,
withSpring,
Easing,
cancelAnimation,
} from '@umituz/react-native-animation';
import Animated from '@umituz/react-native-animation';
function MyComponent() {
const opacity = useSharedValue(0);
const scale = useSharedValue(1);
const style = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ scale: scale.value }],
}));
const animate = () => {
opacity.value = withTiming(1, { duration: 300 });
scale.value = withSpring(1.2);
};
const cleanup = () => {
// IMPORTANT: Always cancel animations in cleanup
cancelAnimation(opacity);
cancelAnimation(scale);
};
useEffect(() => {
return cleanup; // Cleanup on unmount
}, []);
return (
<Animated.View style={style}>
<Button onPress={animate} title="Animate" />
</Animated.View>
);
}Performance Best Practices
1. Always Clean Up Animations
// ❌ BAD: No cleanup
function BadComponent() {
const value = useSharedValue(0);
useEffect(() => {
value.value = withTiming(1, { duration: 1000 });
// Memory leak!
}, []);
}
// ✅ GOOD: Proper cleanup
function GoodComponent() {
const value = useSharedValue(0);
useEffect(() => {
value.value = withTiming(1, { duration: 1000 });
return () => {
cancelAnimation(value); // Prevent memory leak
};
}, []);
}2. Use Worklets for UI Thread Execution
// ❌ BAD: Regular function accessing shared values
const badFunction = () => {
console.log(value.value); // Main thread access
};
// ✅ GOOD: Worklet function
const goodFunction = () => {
'worklet';
console.log(value.value); // UI thread access
};3. Minimize runOnJS Calls
// ❌ BAD: Excessive runOnJS calls
useAnimatedReaction(() => value.value, () => {
runOnJS(callback1)();
runOnJS(callback2)();
runOnJS(callback3)();
});
// ✅ GOOD: Batch JS calls
useAnimatedReaction(() => value.value, () => {
runOnJS(() => {
callback1();
callback2();
callback3();
})();
});4. Use Proper Dependencies
// ❌ BAD: Missing dependencies
useEffect(() => {
animateIn();
}, [visible]); // animateIn not in deps
// ✅ GOOD: All dependencies included
useEffect(() => {
animateIn();
}, [visible, animateIn]);5. Disable Animations When Needed
<AnimatedCard
visible={visible}
disabled={isLowEndDevice || prefersReducedMotion}
>
<Content />
</AnimatedCard>API Reference
AnimatedCard
Performance-optimized card component with automatic cleanup.
Props:
children:React.ReactNode- Content to displayvisible:boolean- Whether card should be visible (default: true)onAnimationEnd:() => void- Callback when entry animation completesstyle:ViewProps['style']- Additional styles to applydisabled:boolean- Disable all animations (default: false)
Ref Methods:
animateIn(): Trigger entry animationanimateNext(callback?): Trigger exit animation followed by entry animation
Features:
- ✅ Automatic cleanup on unmount
- ✅ Memory leak prevention
- ✅ Worklet-optimized animations
- ✅ Race condition prevention
- ✅ React 18+ concurrency support
Animation Presets
Common animation configurations for consistent behavior:
import { AnimationPresets } from '@umituz/react-native-animation';
// Spring presets
AnimationPresets.SPRING // { damping: 15, stiffness: 100, mass: 1 }
AnimationPresets.SPRING_BOUNCY // { damping: 10, stiffness: 200, mass: 1 }
AnimationPresets.SPRING_STIFF // { damping: 20, stiffness: 300, mass: 0.8 }
// Timing presets
AnimationPresets.TIMING_FAST // { duration: 200 }
AnimationPresets.TIMING_NORMAL // { duration: 300 }
AnimationPresets.TIMING_SLOW // { duration: 500 }Performance Modes
Optimize animations based on device capabilities:
import { PerformanceMode, PerformanceConfig } from '@umituz/react-native-animation';
const config: PerformanceConfig = {
mode: PerformanceMode.BALANCED,
reducedMotion: true,
frameRateLimit: 60,
};TypeScript Support
Full TypeScript support with comprehensive types:
import type {
AnimatedStyle,
SharedValue,
AnimatedCardProps,
AnimatedCardRef,
AnimationState,
TransitionConfig,
CardAnimationConfig,
SpringConfig,
TimingConfig,
PerformanceMode,
PerformanceConfig,
} from '@umituz/react-native-animation';Common Issues & Solutions
Issue: Memory Leaks
Problem: Animations continue running after component unmounts.
Solution: Always cleanup animations in useEffect return:
useEffect(() => {
return () => {
cancelAnimation(sharedValue);
};
}, []);Issue: Race Conditions
Problem: Multiple animations running simultaneously conflict.
Solution: Cancel existing animations before starting new ones:
const startAnimation = () => {
cancelAnimation(value); // Cancel first
value.value = withTiming(target);
};Issue: Performance Degradation
Problem: Too many animations running simultaneously.
Solution: Reduce shared values and batch updates:
// Instead of 5 separate shared values
const opacity = useSharedValue(0);
const scale = useSharedValue(1);
const rotate = useSharedValue(0);
// Use a single object when possible
const transform = useSharedValue({ opacity: 0, scale: 1, rotate: 0 });Changelog
1.6.0 (2026-03-22)
- ✅ Fixed critical memory leak issues
- ✅ Added proper animation cleanup
- ✅ Implemented worklet optimizations
- ✅ Fixed useEffect dependency bugs
- ✅ Added React 18+ concurrency support
- ✅ Eliminated race conditions
- ✅ Added performance mode support
- ✅ Improved TypeScript types
- ✅ Added accessibility support (reduced motion)
1.5.0
- Removed domain-specific animations
- Improved package structure
License
MIT
