Write once use anywhere : React native components
React native is the latest cool thing in mobile development world now a days backed by super cool “Facebook”. People are trying their hands more and more on it. This blog is for all those people who have just started working on React Native and looking for modularizing their code into component based architecture for re-usability.
So let’s start with a use-case. Let’s say I need a counter in my react native mobile app and I need to use it on more than one pages. As a developer my first thought should be to make it a stand alone component that I can plug in anywhere and customizable as well. Now we will create that reusable counter component which looks something like this :
We are assuming you are already familiar with react basics and redux. We have created a counter.component.js
that we will be importing anywhere we want to use this.
[js]
import React, {Component} from ‘react’;
import {
StyleSheet,
View,
Text,
TouchableNativeFeedback
} from ‘react-native’;
let Icon = require(‘react-native-vector-icons/MaterialIcons’);
export default class CounterComponent extends Component {
constructor(props) {
super(props);
}
render() {
var TouchableElement = TouchableNativeFeedback;
return (
<View style={styles.container}>
<TouchableElement onPress={() => { this.props.buttonClickDec(this.props.differenceCount);}}>
<View style={styles.calcContainer} >
<Icon style={styles.icon} name=’remove’ size={26} />
</View>
</TouchableElement>
<Text style={styles.valueText}>{this.props.count}</Text>
<TouchableElement onPress={() => { this.props.buttonClickInc(this.props.differenceCount)}}>
<View style={styles.calcContainer}>
<Icon style={styles.icon} name=’add’ size={26} />
</View>
</TouchableElement>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: ‘row’,
justifyContent: ‘center’
},
calcContainer : {
borderRadius: 50,
borderWidth: 1,
borderColor: ‘#ccc’,
width: 40,
height: 40,
justifyContent: ‘center’,
alignItems: ‘center’
},
valueText : {
paddingVertical : 9,
color: ‘#3336FF’,
marginHorizontal: 10,
fontSize:18
}
});
[/js]
React native’s in-built tags like View, Text, TouchableNativeFeedback etc are very much similar to our HTML tags. Here we have used react-native-vector-icons/MaterialIcons
module for generating + and – icons.
Let’s use this component inside another react native component. I have a page where user needs to enter quantity of item they are buying.
[js]
import React, {Component} from ‘react’;
import {
StyleSheet,
View,
Image,
Text,
TouchableNativeFeedback
} from ‘react-native’;
import CounterComponent from ‘../components/counter.component’;
import {increment, decrement} from ‘../actions/buyItem.actions’;
import {connect} from ‘react-redux’;
class BuyItemComponent extends Component {
constructor(props) {
super(props);
}
incrementCounter(diff) {
//call your action here for incrementing the value
this.props.dispatch(increment(diff));
}
decrementCounter(diff) {
//call your action here for incrementing the value
this.props.dispatch(decrement(diff));
}
render() {
let self = this;
var TouchableElement = TouchableNativeFeedback;
return (
<View style={styles.container}>
<View>
<View style={[styles.contentStyle, styles.lineBorder]}>
<CounterComponent buttonClickInc={self.incrementCounter.bind(self) }
buttonClickDec={self.decrementCounter.bind(self) } count={this.props.item.count} differenceCount=’1’/>
</View>
<View style={styles.bottomButton}>
<TouchableElement>
<View style={styles.button}>
<Text style={styles.buttonText} >BUY</Text>
</View>
</TouchableElement>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: ‘#fff’
},
bottomButton: {
marginHorizontal: 10,
marginTop: 20,
marginBottom: 5
},
textHeading: {
color: ‘grey’,
fontSize: 12,
paddingBottom: 12
},
contentStyle: {
padding: 16
},
lineBorder: {
borderBottomWidth: 2,
borderColor: ‘#f4f4f4’,
paddingBottom: 16
},
button: {
backgroundColor: ‘#2AB223’,
borderRadius: 4,
padding:10
},
buttonText : {
color : ‘#fff’,
textAlign:’center’,
fontWeight: ‘bold’
}
});
const mapStateToProps = function (state) {
return state
};
const buyItems = connect(mapStateToProps)(BuyItemComponent);
export default buyItems;
[/js]
Here you can see, we pass start count and difference as attributes which are customizable. In this case we pass difference as 1 so user can increase or decrease the count by 1. We just need to implement incrementCounter
and decrementCounter
methods here which will be called when buttons are clicked. Your logic for calling actions which in turn call reducers goes there.
Similarly we can make the “BUY” button used above as a component, where I can just pass the text and method that I need to call on its click. I can use it anywhere. Now that’s an exercise for you guys. Try creating Button Component on your own and keep exploring. 🙂