Reputation: 444
What is the correct way to do animations when removing something from the DOM?
It seems like no matter what I do, when I remove something form the dom, it doesn't trigger a re render until the items are removed and then it snaps away out of view instead of transitioning before it removes the data. Here is an example of something I've tried.
const [isExpanded, setIsExpanded] = useState(false);
const [isVisible, setIsVisible] = useState(false);
const toggleReplies = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
if (isExpanded) {
setIsVisible(false);
setTimeout(() => {
setIsExpanded(false);
}, 300);
} else {
setIsExpanded(true);
setIsVisible(true);
}
};
return (
<View style={styles.container}>
<Button title="Toggle Replies" onPress={toggleReplies} />
{isVisible && (
<View style={styles.replyBox}>
<Text>This is a reply!</Text>
</View>
)}
</View>
);
};
Upvotes: 1
Views: 385
Reputation: 907
Christopher.
Animating elements out upon removing them from the DOM can be complex because React removes the element without any further ado, and for that reason, the element simply "pops" out and doesn't animate away as expected. There are two solid approaches to fix this:
Import Animated and useRef:
import React, { useState, useRef } from 'react';
import { View, Text, Button, Animated, StyleSheet } from 'react-native';
Setup Animation:
const MyComponent = () => {
const [isVisible, setIsVisible] = useState(true);
const fadeAnim = useRef(new Animated.Value(1)).current; // Initial opacity value
const toggleReplies = () => {
if (isVisible) {
// Fade out animation
Animated.timing(fadeAnim, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start(() => {
setIsVisible(false); // Hide component after fade out
});
} else {
setIsVisible(true); // Show component
// Reset opacity to 1 before fade in
fadeAnim.setValue(0);
// Fade in animation
Animated.timing(fadeAnim, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
}
};
return (
<View style={styles.container}>
<Button title="Toggle Replies" onPress={toggleReplies} />
{isVisible && (
<Animated.View style={{ ...styles.replyBox, opacity: fadeAnim }}>
<Text>This is a reply!</Text>
</Animated.View>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
replyBox: {
padding: 20,
backgroundColor: 'lightgray',
marginTop: 10,
},
});
export default MyComponent;
isVisible
state.useNativeDriver: true
for better performance.duration
value to control the speed of the animation.This method provides a smooth transition effect when showing and hiding components in React Native.
Hope this helps! Let me know if you have any more questions.
Upvotes: -1
Reputation: 32572
I don't know what exactly you want to do with fading out, but definitely, your solution is animation, I think the following codes can help you reach your goal:
import React from 'react';
import type {FC, ReactNode} from 'react';
import Animated, {
FadeInUp,
FadeOutUp,
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated';
interface FadeViewProps {
id: string | number; // <== pass a unique id here
children?: ReactNode;
}
const FadeView: FC<FadeViewProps> = ({ id, children }) => {
const opacity = useSharedValue(1);
const wrapperAnimantedStype = useAnimatedStyle(() => {
opacity: opacity.value,
});
return (
<Animated.View
key={id}
entering={FadeInUp}
exiting={FadeOutUp}
style={[wrapperAnimantedStype]}
>
{children}
</Animated.View>
When you try to render it or remove it from UI it will show you a fade-out animation. You can get inspired by it to improve your exact desire.
Upvotes: 1
Reputation: 587
I've seen a bug before where you have to move your Layoutanimation.Confi..
outside the function call. Maybe in a useEffect
or just in the render of the function after initialisation and see if that works.
For Layout Animation to work on android, I you have to enable setLayoutAnimationEnabledExperimental
.
I'm assuming you are already using React Navigation, so you will have React Native Reanimated already available in your project. You can start by adding it in your package.json if not already present. Then you can use it to do enter/exit Animations quite easily.
Upvotes: 0
Reputation: 340
This is a common problem for animating the react components and elements, react is creating and destroying the dom nodes, so the browser does not apply any styles to elements that are non existing.
2 options to achieve what you want, just change the styles and keep the nodes in dom, or you can use https://reactcommunity.org/react-transition-group/css-transition for adding "exit", "enter" styles to elements just before they will get destroyed / created.
Upvotes: 0