React Native中react-native-animatable返回页面后动画不重放问题
Hey there! I see you're running into an issue where your animatable views only play their animations on the first load, but not when navigating back to the Home tab. You're spot-on about the root cause—since the component doesn't remount when you return, the animation prop only triggers once on initial mount. Let's walk through a couple of solid solutions to fix this.
Solution 1: Manually Trigger Animations on Screen Focus (Recommended)
The cleanest approach is to listen for when the Home screen comes back into focus, then manually trigger each animation using the animatable component's animate() method. Here's how to adjust your class component code:
Step 1: Create Refs for Animatable Views
First, add refs to each of your animatable <View> components so we can call their animation methods later:
import React, { Component } from 'react'; // ... other imports class Home extends React.Component { constructor(props) { super(props); // Create refs for each animated view this.bounceLeft1Ref = React.createRef(); this.bounceRightRef = React.createRef(); this.bounceLeft2Ref = React.createRef(); }
Step 2: Add Navigation Focus Listener
Next, set up a listener for the focus event (from React Navigation) in componentDidMount. When the screen focuses, we'll call the animate() method on each ref:
componentDidMount() { const { navigation } = this.props; // Listen for when the screen comes into focus this.focusListener = navigation.addListener('focus', () => { // Trigger each animation this.bounceLeft1Ref.current?.animate('bounceInLeft'); this.bounceRightRef.current?.animate('bounceInRight'); this.bounceLeft2Ref.current?.animate('bounceInLeft'); }); } // Clean up the listener when the component unmounts componentWillUnmount() { this.focusListener(); }
Step 3: Attach Refs to Your Views
Update your render method to assign the refs to each animatable <View>:
render() { return ( <View style={styles.container}> <View ref={this.bounceLeft1Ref} animation='bounceInLeft' style={styles.container1} > <View style={styles.card1}> <ImageBackground source={require('../images/pictures/runop.jpg')} style={{width:'100%', height:200, }}> <Text style={{fontSize:30, alignSelf:'center', color:'white', fontFamily:Fonts.Nunito}} > Sport Schema's</Text> </ImageBackground> </View> </View> <View ref={this.bounceRightRef} animation='bounceInRight' style={styles.container2} > <View style={styles.card2}> <Image source={require('../images/pictures/foodop.jpg')} style={{width:'100%', height:200}}/> </View> </View> <View ref={this.bounceLeft2Ref} animation='bounceInLeft' style={styles.container3} > <View style={styles.card3}> <Image source={require('../images/pictures/blogop.jpg')} style={{width:'100%', height:200}}/> </View> </View> </View> ); }
This method is efficient because it doesn't force a full component remount—we just trigger the animations directly when needed.
Solution 2: Force Component Remount with a Key
If you prefer a more brute-force approach (though less efficient), you can force the Home component to remount by updating a key prop whenever the screen focuses. This will re-run all initial mount logic, including the animations:
class Home extends React.Component { state = { componentKey: Date.now() }; componentDidMount() { this.focusListener = this.props.navigation.addListener('focus', () => { // Update the key to trigger a remount this.setState({ componentKey: Date.now() }); }); } componentWillUnmount() { this.focusListener(); } render() { return ( <View key={this.state.componentKey} style={styles.container}> {/* Your existing animatable views here */} </View> ); } }
Note: This will re-render your entire Home component and all its children, which might cause unnecessary performance overhead if your component is complex. Stick with Solution 1 unless you have a specific reason to use this.
Bonus: Function Component Version
If you ever decide to convert your class component to a function component, you can use useFocusEffect from React Navigation along with useRef:
import React, { useRef } from 'react'; import { useFocusEffect } from '@react-navigation/native'; // ... other imports const Home = ({ navigation }) => { const bounceLeft1Ref = useRef(null); const bounceRightRef = useRef(null); const bounceLeft2Ref = useRef(null); useFocusEffect( React.useCallback(() => { bounceLeft1Ref.current?.animate('bounceInLeft'); bounceRightRef.current?.animate('bounceInRight'); bounceLeft2Ref.current?.animate('bounceInLeft'); }, []) ); return ( <View style={styles.container}> <View ref={bounceLeft1Ref} animation='bounceInLeft' style={styles.container1}> {/* Card content */} </View> {/* Repeat for other views */} </View> ); };
Give these methods a try—your animations should now fire every time you navigate back to the Home screen!
内容的提问来源于stack exchange,提问作者Re-Angelo

