Our Thoughts
Vertika Jain
JS Full Stack Developer
30 May, 2022 8 MIN READ

A Beginner's Guide to React Native

 

How does React Native Work: Views

In Mobile development, a View is the basic building block of UI: a small rectangular element on the screen that can be used to display text, images, or respond to user input. Even the smallest visual elements of an app, like a line of text or a button, are kinds of views.

A beginner's guide to React Native

According to the React Native site's introduction, you invoke the views with JavaScript using React components. React Native creates the corresponding Android and iOS views at runtime for those components. Because React Native components are backed by the same views as Android and iOS, React Native apps look, feel, and perform like any other app.

 

Setup

  1. Install expo-CLI globally using sudo npm install -g expo-cli
  2. Initialize project expo init my-first-react-native-project. This will create a basic project setup with all the initial files like package.json, etc.
  3. Go to the project directory in your favorite editor cd my-first-react-native-project/
  4. Run the expo-cli server using yarn start OR expo start
  5. In case it shows this error on the web browser - “Expo Developer Tools is disconnected from Expo CLI”, (EMFILE: too many open files) then install watchman: brew install watchman
  6. Download the expo client app on your mobile.
  7. Scan the QR code provided in the web browser, and you will be able to view the Javascript running.
     

💡 As a result of the automatic fast reload feature of React Native, there is no need to restart manually after the completion of all these steps.

The app.js file contains the main component, which can be edited as per the project requirements.

 

Assumptions

  1. The code is written with respect to the React Functional components.
  2. All core components have to be initially imported from react-native in your code -
import { StyleSheet, Text, View, ScrollView, FlatList, Alert, TouchableWithoutFeedback, Keyboard } from 'react-native';

 

Adding CSS in React Native

  • React Native does not use CSS. It only emulates the idea of CSS. Therefore, we implement CSS using the style prop in the component, which refers to the CSS properties stored in an object.
  • A StyleSheet is an abstraction similar to CSS StyleSheets. This makes the code easier to understand and in case of any error in the style properties, it is shown at compile time rather than run time.
const styles = StyleSheet.create({
  container: {
    backgroundColor: '#fff'
    alignItems: 'center',
    justifyContent: 'center',
  },
  boldText: {
    fontWeight: 'bold'
  },
}
  • The idea of inheritance of CSS properties does not work in the case of React Native. One needs to specify styles for each element. With one exception - Text widgets within Text widgets.
<Text>Name is <Text style={styles.boldText}>{name}</Text> !</Text>

 

Understanding the React Native Core Components

Core components are a set of essential, ready-to-use native components for quick and easy mobile application development.

  • <View> is used to wrap other elements.
  • <Text> is used to display any textual content.
  • You cannot write anything without the React Native core components. Not even HTML tags such as <p> can be used. This will result in an error.
  • In react native, <Button/> is a self closing tag. And you can send data as prop to this element. For example, <Button title='update state'/>. This will have some styles by default, but you cannot add styles property to a button in react native, hence it should be wrapped around a <View> tag to add styles to it.
<View style={styles.header}>
<Text style={styles.boldText}>Name is {name} </Text>
   <Text>Age is {age} </Text>
</View>
  • <TextInput> is used to take inputs from a user. It has the following props available -
    1. placeholder prop
    2. multiline for text with multiple lines for form input
    3. onChange and onChangeText event listeners. onChange is useful when we need access to underlying native-event containing target, eventCount and text. While onChangeText only provides access to underlying text that changed
    4. keyboardType prop is useful to set the type of inputs that a user can provide. For instance a phone number will only contain numbers. Email address should follow a regex, etc.
      1. numeric
      2. email_address
<TextInput
   style={styles.input}
   placeholder='e.g. Vertika'
   onChangeText={(val) => setName(val)
   multiline>
</TextInput>
<TextInput
style={styles.input}
   placeholder='e.g. 20'
   onChangeText={(val) => setAge(val)}
   keyboardType={'numeric'}>
</TextInput>
  • Lists of data can be rendered using the JS method map(). Same as it is done in other JS frameworks. Similarly, you need to have a key for each list item. When the list or any content exceeds the page dimensions, you need to add <ScrollView>, wrapping up the content that should get scrolled. This is suitable for shorter lists.
const colors = [
  { name: 'red', key: 1 },
  { name: 'blue', key: 2 },
  { name: 'orange', key: 3 },
  { name: 'purple', key: 4 }
]

// In the return method

<ScrollView>
   {colors.map(color =>
      <Text key={color.key} style={colorStyles(color.name)}>{color.name}</Text>
   )}
</ScrollView>

// A separate method using CSS styles Dynamically
const colorStyles = (color) => {
  return {
    marginTop: 20,
    padding: 30,
    backgroundColor: color,
    color: "white"
  }
}
  • <FlatList/> is quite similar to ScrollView, except that it performs much better in terms of memory and processing time. Since it renders items lazily, when they are about to appear, and removes items that scroll way off-screen, therefore, it is better for longer lists. It automatically looks for the key property in each item in a list. Few mostly used properties of FlatList are as follows-
    1. data: pass the list/array that has to be rendered.
    2. renderItem: renders the items of the list mentioned in the data prop.
    3. keyExtractor: used in case the name of the key is something other than a key.
    4. numColumns: tells the number of columns in which the data should be rendered.
<FlatList
   numColumns={2}
   keyExtractor={item => item.id}
   data={colors}
   renderItem={({ item }) => ( // has to be named as "item"
     <Text style={colorStyles(item.name)}>{item.name}</Text>
   )}
/>
  • <TouchableOpacity> is used when you want an element to go opaque, or fade out a little bit when touched. You can also use the onPress() property for adding other functionalities.
<TouchableOpacity onPress={() => pressHandler(item.id)}>

   <Text style={colorStyles(item.name)}>{item.name}</Text>

</TouchableOpacity>
  • <Alert> is used to launch an alert dialog with the specified title and message. It can also have multiple buttons as option, providing different functionalities using the onPress() handler.
Alert.alert('OOPS!', 'Todo must be atleast 3 characters long.', [
  { text: 'Gotcha!', onPress: () => console.log('alert closed.') }
])
  • <TouchableWithoutFeedback> wraps a single component based on requirement. When pressed, the functionality provided in onPress() handler shall execute.
<TouchableWithoutFeedback
      onPress={() => Keyboard.dismiss()} 
<WrappedComponent/>
</TouchableWithoutFeedback>
  • The Keyboard module used in the above example listens to native events and handles them using methods such as dismiss().

 

FlexBox in React Native

  • A flex-box takes up the whole space available in the mobile screen. It can be set in styles using -
const styles = StyleSheet.create({
  container: { // outermost component
    flex: 1,
flexDirection:'row',
    justifyContent:'space-around',
alignItems:'stretch',
  }
})
  • The default behavior of flex is 'column'. You can set it as flexDirection:'row' for horizontal alignment of data.
  • Setting flexDirection without flex:1 takes only the required space and not the whole screen.
  • The justifyContent property enables us to set the item positions in a flex box to the center, left (default), right, spread (space-around and space-between), etc.
  • The alignItems property sets the alignment of the flex box items w.r.t to their position.
  • The space for the items is divided based on each element's flex properties, like flex:2 for one element, flex:3 for another, etc.

 

Adding Custom Fonts to React Native

To add custom fonts to your react-native project, the expo-font library can be used. With the help of this, fonts can be loaded from the web and then be used in React Native components. One can download the required fonts and copy them into the assets folder, and include them in the App.js or other JS file using the loadAsync() method.

import * as Font from 'expo-font';
const getFonts = () => { return Font.loadAsync({
  'nunito-regular': require('./assets/fonts/Nunito-Regular.ttf'),
  'nunito-bold': require('./assets/fonts/Nunito-Bold.ttf')
})}

Apps.js


loadAsync() is a highly efficient built-in method, that loads font from a static resource. Any string can be used as the font-family name. Secondly, you need to add these fonts to the styles of your components.

<Text style={{fontFamily: 'nunito-bold'}, fontSize: 20}>This is home screen</Text>

MyComponent.js


It is a good UI approach (for better optimization) to display components to the screen only when the assets such as custom fonts, icons, and logo images are completely loaded. Therefore, state management (the useState hook) is applicable here, along with another expo library called expo-app-loading which tells the expo-splash-screen to keep the screen visible while the AppLoading component is mounted. You can read more about it here.

Install the library using - expo install expo-app-loading

import AppLoading from 'expo-app-loading';
export default function App() {
  const [fontLoaded, setFontLoaded] = useState(false);
  if (fontLoaded) {
    return <MyComponent />
  }
  else {
    return (
      <AppLoading
        startAsync={getFonts}
        onFinish={() => setFontLoaded(true)}
        onError={(err) => console.log(err)}
      />);
  }

}

Apps.js

 

The AppLoading component makes a call to the getFonts() method, and when the fonts are finished loading, we call the setFontLoaded() method and set fontLoaded to true causing re-rendering. Thus, <MyComponent/> gets rendered.

 

Conclusion & Future Work

With React Native, programmers can create multi-platform applications with one technology - React, making the product cost-efficient. The Core components that we just discussed and many more, map directly to the platform’s native UI building blocks. This was just an introductory blog, and there is much more to learn in React Native, such as Navigation, Error handling, Images, Forms, etc. that shall be covered soon by us. Stay tuned for more updates! 

Vertika Jain