My Jump from React to React Native
I have recently created my first React Native application using Rails as the backend. Here is a quick demo of my app FitCo.
Major differences between React & React Native
- Routes replaced with navigation.
- DOM events such as: event.target will not work in RN. (See more here.)
- HTML is deprecated in RN. No more <html> tags of any sort.
- Handling events onClick to onPress.
- List an array of objects within a component requires FlatList.
- LocalStorage to AsyncStorage.
- CSS to RN Stylesheet.
Navigation
Navigation is the biggest change coming from a web application to mobile. At first it can be confusing deciding when to use a stack navigator, tab navigator, or draw navigator when connecting one to another. When creating your wireframes I recommend drawing out a tree structure to visualize the navigation.
For my app, I wanted two different user experiences. One for the instructors and the other for students. They both have different stack & tab navigations:
As shown above, there are two tab navigators, each with its own list of screens or nested stack navigators. Planning out each navigation prior to starting a project will help organize your source code.
Please refer to this link: https://reactnavigation.org/ for examples and more information on navigation types. Installation and imports are also required.
Event Handling
Event handling is different on mobile. React Native comes with gestures, button press, scroll view, etc. Thus, a property that is commonly used is onPress or onChangeText.
<FontAwesome
name="id-badge"
size={20}
/>
<TextInput
style={styles.textInput}
value={this.state.username}
placeholder="Username"
placeholderTextColor='#A9A9A9'
type='username'
onChangeText={this.changeHandler("username")}
/>
... changeHandler = (name) => (text) => {
this.setState({ [name]: text});
}
Example of onPress below:
<Text style={styles.text_account}>Select Account</Text>
<View style={styles.buttons}>
<CheckBox
center
iconRight
title='Coach'
checked={this.state.flag}
onPress={() => {this.setState({flag: true})}}
/>
<CheckBox
center
iconRight
title='Student'
checked={!this.state.flag}
onPress={() => {this.setState({flag: false})}}
/>
</View>
FlatList
Since HTML is not supported in React Native, FlatList is a workaround.
<FlatList
data={comments}
keyExtractor={item => `${item.key}`}
renderItem={({ item }) => <Comment {...item} />}
ItemSeparatorComponent={this.renderSeparator}
/>
Common Issues: "VirtualizedList: missing keys for items, make sure to specify a key property on an item or provide a custom keyExtractor"
Make sure to set the KeyExtractor. keyExtractor={(item, index) => item.key}
More on FlatList: https://reactnative.dev/docs/flatlist.html
AsyncStorage
Instead of using localStorage, React Native comes with AsyncStorage. This comes in handy when checking for the current user’s token.
More info here: https://reactnative.dev/docs/asyncstorage
Other Useful Tools In React Native
ScrollView from ‘react-native’
A wrapper works wonders with horizontal scrolling. As shown in the demo earlier for Trending Posts & Trending Coaches.
<ScrollView>
<Animatable.View
delay={1200}
animation="fadeInLeft"
duraton="9000">
<ImageBackground
source={require('../assets/images/homescreen.png')}
style={{width: '100%', height: 270}}
imageStyle={{borderBottomRightRadius:65}}>
<View style={styles.searchContainer}>
<Text style={styles.userGreet}>
Welcome to FitCo</Text>
<Text style={styles.userText}>
Check out the lastest Posts and featured Coaches</Text>
</View>
</ImageBackground>
</Animatable.View>
<ScrollView>
More info here: https://reactnative.dev/docs/scrollview
TouchableOpacity from ‘react-native’
A wrapper for responsive touch to your views, text, button, etc.
<TouchableOpacity
style={styles.button3}
onPress={() => onPressLeft()}>
<Text style={styles.dislike}>
<FontAwesome name="times-circle"
size={65}
style={{color: '#DC143C'}}/>
</Text>
</TouchableOpacity>
Dimensions from ‘react-native’
Useful for setting default width/height when applying flex-box, stylesheets, etc. const fullWidth = Dimensions.get('window').width;
Additionally, look into PixelRatio: https://reactnative.dev/docs/pixelratio
ActivityIndicator from ‘react-native’
Used for loading screen and transitioning from one screen to another.
{this.props.follows.isLoading ?
<ActivityIndicator size="small"/>
:
// ... render screen
}
StyleSheet from ‘react-native’
Styling is straightforward and only requires a simple import.
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
...
Recommendation
Applying Redux and/or React Hooks to your application will help manage state from one screen to another without having to worry about passing props around.
Take advantage of component lifecycle if you require a re-render. ComponentDidMount & ComponentDidUpdate comes in handy in most cases.
Useful Libraries Used In My Application
General:
react-redux
redux-thunk
react-native-popup-dialog
react-navigation
react-native-nodemediaclient
react-native-video
react-native-image-picker
Styling:
reanimated-bottom-sheet
react-native-card-stack-swiper
react-native-animatable
react-native-vector-icons (materialIcon, fontAwesome, Ionicons)
Dev tools:
remote-redux-devtools
react-devtools
As always, thank you for reading!