This tutorial explains how to add and remove component with animation in react native application. In this example we are going to create add and remove functionality inside the scrollview. In order to use these functionalities in side the scrollview, you have to perform below operation :
Download Now
1. When user click on add button, then it will add new entry inside the scrollview.
2. When user click on delete button, then it remove that particular enter from the scrollview.
React Native Dynamically Add / Remove Component with Animation :
Lets see the complete source code App.js component that helps to dynamically add and remove component with animation in react native application.
Video Demo :
Video Demo :
project structure :
Step 1: Create a new react native project, if you don’t know how to create a new project in react native just follow this tutorial.
Step 2: Create a new Item component inside the src folder. This component helps to add and remove content inside the scrollview with animation effect.
Step 3: Through react , react-native packages import all required components.
Step 3: Through react , react-native packages import all required components.
import React, { Component } from 'react'; import { Animated, Text, TouchableOpacity, StyleSheet,Image, Dimensions, Platform, UIManager } from 'react-native';
Step 4: Define constant named as width, which capture the width of the device automatically with the help of Dimension component.
const width = Dimensions.get('window').width;
Step 5: Lets create constructor block inside your Item component.
constructor() { super(); this.animatedValue = new Animated.Value(0); if (Platform.OS === 'android') { UIManager.setLayoutAnimationEnabledExperimental(true); } }
Step 6: Lets implement shouldComponentUpdate method. Basically, shouldComponentUpdate is a lifecycle method of react and used to improve the performance of the app. shouldComponentUpdate method returns a boolean either true or false . If it returns true then component re-renders otherwise react skips the re-rendering process.
shouldComponentUpdate(nextProps, nextState) { if (nextProps.item.id !== this.props.item.id) { return true; } return false; }
Step 7: Lets implement componentDidMount method. This is the place where our animation will work for adding a component and after completing the animation I am calling afterAnimationComplete method which is received as prop from parent component.
componentDidMount() { Animated.timing( this.animatedValue, { toValue: 0.5, duration: 500, useNativeDriver: true } ).start(() => { this.props.afterAnimationComplete(); }); }
Step 8: Lets create removeItem function that helps to execute the removing animation and again I am calling removeItem method to actually remove the selected item from ScrollView and this method is also received as prop from parent component.
removeItem = () => { Animated.timing( this.animatedValue, { toValue: 1, duration: 500, useNativeDriver: true } ).start(() => { this.props.removeItem(this.props.item.id); }); }
Step 9: Implement render method inside the App class and wrapped the below layout design inside the root View component. when we add a new component then element’s translateX position is equal to the -width and component animates from -width to as you can see in the translateAnimation ‘s outputRange and when user clicks on the remove icon on any component then component animates from to width (as you can see in the translateAnimation ‘s outputRange) and opacityAnimation also works along with translateAnimation .
render() { const translateAnimation = this.animatedValue.interpolate({ inputRange: [0, 0.5, 1], outputRange: [-width, 0, width] }); const opacityAnimation = this.animatedValue.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0, 1, 0] }); return ( <Animated.View style={[ styles.viewHolder, { transform: [{ translateX: translateAnimation }], opacity: opacityAnimation }]} > <Text style={styles.displayText}> Row Now : {this.props.item.text} </Text> <TouchableOpacity style={styles.removeBtn} onPress={this.removeItem} > <Image source={require('../../images/deleteButton.png')} style={styles.btnImage} /> </TouchableOpacity> </Animated.View> ); }
Step 10 : Apply the below style sheet design.
const styles = StyleSheet.create( { viewHolder: { paddingVertical: 15, backgroundColor: '#2196f3', justifyContent: 'center', alignItems: 'flex-start', margin: 4, paddingLeft: 15, borderRadius: 10 }, displayText: { color: 'white', fontSize: 25, paddingRight: 17 }, removeBtn: { position: 'absolute', right: 13, width: 30, height: 30, borderRadius: 15, justifyContent: 'center', alignItems: 'center', backgroundColor: 'white' }, btnImage: { resizeMode: 'contain', width: '100%', }, });
Lets see the below complete source code for Item component.
Item.js
import React, { Component } from 'react'; import { Animated, Text, TouchableOpacity, StyleSheet,Image, Dimensions, Platform, UIManager } from 'react-native'; const width = Dimensions.get('window').width; export default class Item extends Component { constructor() { super(); this.animatedValue = new Animated.Value(0); if (Platform.OS === 'android') { UIManager.setLayoutAnimationEnabledExperimental(true); } } shouldComponentUpdate(nextProps, nextState) { if (nextProps.item.id !== this.props.item.id) { return true; } return false; } componentDidMount() { Animated.timing( this.animatedValue, { toValue: 0.5, duration: 500, useNativeDriver: true } ).start(() => { this.props.afterAnimationComplete(); }); } removeItem = () => { Animated.timing( this.animatedValue, { toValue: 1, duration: 500, useNativeDriver: true } ).start(() => { this.props.removeItem(this.props.item.id); }); } render() { const translateAnimation = this.animatedValue.interpolate({ inputRange: [0, 0.5, 1], outputRange: [-width, 0, width] }); const opacityAnimation = this.animatedValue.interpolate({ inputRange: [0, 0.5, 1], outputRange: [0, 1, 0] }); return ( <Animated.View style={[ styles.viewHolder, { transform: [{ translateX: translateAnimation }], opacity: opacityAnimation }]} > <Text style={styles.displayText}> Row Now : {this.props.item.text} </Text> <TouchableOpacity style={styles.removeBtn} onPress={this.removeItem} > <Image source={require('../../images/deleteButton.png')} style={styles.btnImage} /> </TouchableOpacity> </Animated.View> ); } } const styles = StyleSheet.create( { viewHolder: { paddingVertical: 15, backgroundColor: '#2196f3', justifyContent: 'center', alignItems: 'flex-start', margin: 4, paddingLeft: 15, borderRadius: 10 }, displayText: { color: 'white', fontSize: 25, paddingRight: 17 }, removeBtn: { position: 'absolute', right: 13, width: 30, height: 30, borderRadius: 15, justifyContent: 'center', alignItems: 'center', backgroundColor: 'white' }, btnImage: { resizeMode: 'contain', width: '100%', }, });
Step 11: Open App.js File in your favorite code editor and erase all code and follow this tutorial.
Step 12: Through react , react-native packages import all required components.
Step 12: Through react , react-native packages import all required components.
import React, { Component } from 'react'; import { AppRegistry,TouchableOpacity, View, StyleSheet, ScrollView, Image, LayoutAnimation, } from 'react-native'; import Item from './src/components/Item.js'
Step 13: Lets create constructor block inside your App component.
constructor() { super(); this.state = { valueArray: [], disabled: false } this.addNewEle = false; this.index = 0; }
Step 14: Lets create afterAnimationComplete function. Remember, this method is called by Item component after completing the adding component animation. In this method, I am going to set false the disabled state, which re-enables the add component (+) button and allows to add new component.
afterAnimationComplete = () => { this.index += 1; this.setState({ disabled: false }); }
Step 15: Lets create addMore function. This method is responsible to add a new object into array and disable the add button while running adding component animation.
addMore = () => { this.addNewEle = true; const newlyAddedValue = { id: "id_" + this.index, text: this.index + 1 }; this.setState({ disabled: true, valueArray: [...this.state.valueArray, newlyAddedValue] }); }
Step 16: Lets create remove function. This method is responsible for removing the selected item from array and applying the LayoutAnimation to re-arrange the remaining components with nice animation.
remove(id) { this.addNewEle = false; const newArray = [...this.state.valueArray]; newArray.splice(newArray.findIndex(ele => ele.id === id), 1); this.setState(() => { return { valueArray: newArray } }, () => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); }); }
Step 17: Implement render method inside the App class and wrapped the below layout design inside the root View component.
render() { return ( <View style={styles.container} > <ScrollView ref={scrollView => this.scrollView = scrollView} onContentSizeChange={() => { this.addNewEle && this.scrollView.scrollToEnd(); }} > <View style={{ flex: 1, padding: 4 }}> {this.state.valueArray.map(ele => { return ( <Item key={ele.id} item={ele} removeItem={(id) => this.remove(id)} afterAnimationComplete={this.afterAnimationComplete} /> ) })} </View> </ScrollView> <TouchableOpacity activeOpacity={0.8} style={styles.addBtn} disabled={this.state.disabled} onPress={this.addMore} > <Image source={require('./images/addButton.png')} style={styles.btnImage} /> </TouchableOpacity> </View> ); }
Step 18 : Apply the below style sheet design.
const styles = StyleSheet.create( { container: { flex: 1, }, addBtn: { position: 'absolute', right: 25, bottom: 25, width: 70, height: 70, justifyContent: 'center', alignItems: 'center', borderRadius: 30, backgroundColor: 'white' }, btnImage: { resizeMode: 'contain', width: '100%', }, });
Lets see the complete source for App component in react native application
App.js
import React, { Component } from 'react'; import { AppRegistry,TouchableOpacity, View, StyleSheet, ScrollView, Image, LayoutAnimation, } from 'react-native'; import Item from './src/components/Item.js' export default class App extends Component { constructor() { super(); this.state = { valueArray: [], disabled: false } this.addNewEle = false; this.index = 0; } afterAnimationComplete = () => { this.index += 1; this.setState({ disabled: false }); } addMore = () => { this.addNewEle = true; const newlyAddedValue = { id: "id_" + this.index, text: this.index + 1 }; this.setState({ disabled: true, valueArray: [...this.state.valueArray, newlyAddedValue] }); } remove(id) { this.addNewEle = false; const newArray = [...this.state.valueArray]; newArray.splice(newArray.findIndex(ele => ele.id === id), 1); this.setState(() => { return { valueArray: newArray } }, () => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); }); } render() { return ( <View style={styles.container} > <ScrollView ref={scrollView => this.scrollView = scrollView} onContentSizeChange={() => { this.addNewEle && this.scrollView.scrollToEnd(); }} > <View style={{ flex: 1, padding: 4 }}> {this.state.valueArray.map(ele => { return ( <Item key={ele.id} item={ele} removeItem={(id) => this.remove(id)} afterAnimationComplete={this.afterAnimationComplete} /> ) })} </View> </ScrollView> <TouchableOpacity activeOpacity={0.8} style={styles.addBtn} disabled={this.state.disabled} onPress={this.addMore} > <Image source={require('./images/addButton.png')} style={styles.btnImage} /> </TouchableOpacity> </View> ); } } const styles = StyleSheet.create( { container: { flex: 1, }, addBtn: { position: 'absolute', right: 25, bottom: 25, width: 70, height: 70, justifyContent: 'center', alignItems: 'center', borderRadius: 30, backgroundColor: 'white' }, btnImage: { resizeMode: 'contain', width: '100%', }, });
Screenshot :
This is all about Dynamically Add / Remove Component with Animation in React Native. Thank you for reading this article, and if you have any problem, have a another better useful solution about this article, please write message in the comment section.
Nice work, thanks.
ReplyDeletevery nice work thnaks !!!
ReplyDelete