Verónica MartínezMay 17, 2019

Going from React to React Native

Introduction

Since we’ve recently made the jump from React to React Native in one of our projects, we decided it could be a great idea to make a post to share our experience.

On the plus side, the jump wasn’t all that high considering we have experience with React itself. But there are a few differences worth noting, so we’ll be giving a quick overview of the big topics, as well as some of the issues we’ve encountered so far.

Differences

The first difference to note is that, since this code will be running on a native app instead of on the web, we won’t use normal HTML tags, insted, we’ll use <View /> and <Text />. The first one will replace the <div /> tag, while the second will replace all the tags we use for all kinds of texts, like h1 to h6, or even span tags. Attempting to render text outside a Text tag will raise an error.

Next, there is not longer a <button /> component, instead we’ll need to use one of several options provided by React Native, each with a different style, for example: TouchableOpacity will respond to the touch event with an animation using it’s opacity. TouchableNativeFeedback will use the default buttons from Android and iOS when rendering in each OS. TouchableWithoutFeedback on the other hand does not implement any form of style or feedback, which makes it the perfect option to implement custom buttons, and to wrap other components to be interactive.

As with React, each of these interactive components offer a callback to handle the press event (onPress). They also include two very interesting callbacks onPressIn and onPressOut, which we’ve used a lot to implement animations in custom made button components.

Images

In our case, the app we’re developing relies heavily on images, and they’re not exacly the same as on the web. The most important difference we noticed was that the styles applied to the <Image /> component do not apply to the image itsef, but to the container that holds it. So setting the size for the component will not automatically resize the image. It’s works more like setting a background-image style attribute to a <div>. The resizeMode prop controls how the image adjusts to it’s container with the following values: cover, contain, stretch, repeat, center.

One cool feature implemented is the conditional usage of images for Android or iOS, adding a suffix to the image file name, similar to how one would add different resolutions for one image.

Navigation

The de-facto solution for navigation in ReactNative is React Navigation. React Navigation offers a easy-to-use library to implement the most common types of navigation. Included are the DrawerNavigator, SwitchNavigator, and TabNavigator. It also offers the basic StackNavigator, where each transition is stored in a stack.

In the case of the StackNavigator, there are two distinct methods to navigate between routes, push and navigate. Whenever you use push to move to a route, a new item will be added to the navigation stack. This works great for views that use the same screens, but display different information depending on a route paramenter. For example, like viewing products on a store, where you would expect each of the products you viewed to remain in the navigation history. If instead, you use the navigate method, you will be reusing the same screen, not adding new ones to the stack. Navigate will search in the stack for an instance of the route to be pushed, and if it exists, it will navigate back to it instead. That can result in an odd navigation experience, since you will see all the screens above it passing by as you navigate back to that route.

More info about this library can be found in this post.

Styles

In react native, styles are defined using Javascript. Each of the core components accept a prop named style, than can be a plain javascript object or an array of objects. As the last object of the array has precedence over the others, this can be used to accomplish style inheritance. React native provides the method Stylesheet.create to create an abstraction similar to css Stylesheets, that allows the definition of multiple styles in one place. This provides better performance than defining a plain javascript object, as it makes it possible to refer to it by ID instead of creating a new style object every time, and it also allows to send the style only once through the bridge.

import {
  StylesSheet
} from 'react-native'

const styles = StyleSheet.create({
  container:{
    flexDirection: 'row',
    alignItems: 'center',
    justifyConent: 'center'
  },
  text:{
    backgroundColor: 'black',
    fontSize: '15'
  },
  alertText: {
    backgroundColor: 'red',
  }
})

<View style={styles.container}>
  <Text style={[styles.text, styles.alertText]}>Hello world!</Text>
</View>

As you might’ve noticed, prop names are similar to the ones used in CSS, but are written using camel case. There are different props available depending on the core component that we need to style. You can find here the list of View Style Props and Text Style Props.

By default, React Native uses Flexbox in order to layout components. It uses Yoga Framework and it has some differences with CSS, the main ones are that the default value for flexDirection is column and not row and that flex property is a number rather than a string.

Another difference between React and React native is that all dimensions are unitless and represent density independent pixels. One dpi equals one pixel on a medium-density screen, and measures 1 inch. This works in this way to ensure that the dimensions are the same across all devices independently of screen resolutions. If we define the width of a component in px, in low density screens its going to look wider than in a medium resolution screen, as pixels are smaller in size.

One thing we miss from css is style cascading. You can not define a main stylesheet than can be used in each of the components easily. This promotes defining one stylesheet per component, which is a good thing, but complicates the use of shared styles such as helpers and utilities. We’ve created some minumum helper files, with color and dimension constants, and created style components in order to overcome this issue.

React native provides some useful functions that can be used inside Stylesheets. In order to find out the platform in which the app is running, Platform.OS can be used. Also the width and height of the screen are available by using Dimensions.get(‘window’), this would change when the device is rotated.

Tools

In our project we needed to create pixel perfect designs and we wanted to use some tool similar as the ones we were used to in Web Development to display overlays on top of the screen we were developing. That’s how we found Reactotron that not only has this functionality but let us view our application state, dispatch actions and show API requests & responses, so it was a great discovery.

We also use Expo that are a set of tools, libraries and services that intend to make the development faster. We will write another post about this tool to explain how we use it and what are the advantages and disadvantages that we’ve found along the way.

Hope you find this post useful if you are transitioning from React to React Native 😃