10 Weeks of React: Week 3

Arvin Behshad
8 min readMay 9, 2017

--

Dealing with Navigators

Deliverables this week:

  • Fishes app (GIF)

Unfortunately this has been the busiest week for me so far. On top of that I ran into lots of big problems. So this week’s article might not deliver as much as the previous ones. Live and learn.

Most of this week was spent going back to the drawing board and learning instead of doing.

Porting the website to an app

In order to take the next step with React Native I thought that an interesting challenge would be to make an app based on the website that I built last week. For a while now I’ve been curious about the practicalities (if any) of porting a website built in React to a React Native app.

This is essentially what all web development companies advertise. Except they actually do 3x the work.

Learning about Views

I started out by trying to render the sample data from the JSON file onto the view. The JSON consists of a bunch of fishes that I want to present in a scrollable list. This led me to learn about ScrollView and ListView.

fish2 : {
name : 'Lobster',
image : 'http://i.istockimg.com/file_thumbview_approve/32135274/5/stock-photo-32135274-cooked-lobster.jpg',

desc : 'These tender, mouth-watering beauties are a fantastic hit at any dinner party.',

price : 3200,
status : 'available'
},

So right off the bat, a fundamental difference between React and React Native is the type of Views available to display your content. This does require some knowledge of app development as you need to be aware of certain limitations and best-practices.

This makes sense if you think about it. The data and logic can remain the same, but since you’re adapting the content for a new platform you have to be familiar with the rules and limitations that apply. You can’t seamlessly port a React website to a React Native app in the same way that you can’t seamlessly port content designed for a 27" screen, mouse & keyboard to a 5" screen designed for touch input.

Luckily I have some experience building Android apps, so I caught on pretty quickly after reading the documentation. Once you get past these problems though, i.e. if you’ve done this for a while, I think it’s somewhat safe to say that you can access the data in the same way. You can reuse most of the logic and data. It’s the structuring and organizing of the content which is going to be the bottleneck.

Let’s look at one example by comparing ScrollView with ListView.

ScrollView is a generic scrolling container designed for a limited number of items. The reason being that a ScrollView will render every item in its view, even if it is not currently shown on the screen. This will clearly impact performance.

ListView on the other hand is much smarter by only rendering the elements that are currently being displayed. Sometimes this can cause delays if the user scrolls too fast and there’s not enough time to render the items, so I was very pleased to discover all the nice props that I could set, such as initialListSize(number) which pre-renders a given number of items.

Adding the dreaded Navigator

By now I’ve implemented enough navigators to know my way around most common problems. But I’m really hoping that a beginner to React Native discovers this guide before embarking on an otherwise inevitably frustrating mission.

If you just want to learn how to implement a “quick” navigator in React, skip straight to The Easy Way, where you’ll be led through how to implement react-navigation.

For everyone else, here’s an accurate account of some of the problems you’ll come to face before implementing navigation, if you go at it alone.

Problem 1: Too many choices

If you’re a beginner looking for a library to use, you’ll naively look to the docs and discover all of 4 recommended options. Keep in mind, these are just the ones that made the cut.

Turns out that there are way too many opinions on how to build a navigator in the React community, so different teams have built their own.

Let’s be frank and consider the problem with too many choices for navigators. The truth is that you will end up spending way too much time anxiously comparing their features instead of actually implementing one.

I’ll do you a favor and compare what I consider to be the two most interesting navigators. Let’s compare react-navigation (by Facebook and Expo) with native-navigation (by AirBnb).

The latter isn’t mentioned in the docs, further emphasizing my point, however it’s built directly on top of the iOS and Android navigation components. This makes it ideal for developers who want to combine navigation between React components and native code. It’s still in beta though, and the React docs clearly recommend react-navigation.

Problem 2: Most libraries are either deprecated or should be

This goes along with Problem 1. When looking at the available options, only few of them are significant enough to be considered for your next project.

Problem 3: Boilerplate or no?

Several companies have created React Native project boilerplates of various sizes ranging all the way from a few pre-configurations to entire development environments. The point being that they help you get up and running. Some of these also include navigators but others don’t (just to further add to the confusion). Here’s a list of headaches:

I’m interested to try out Expo and Ignite. But for now I’m not choosing any, as my focus is doing everything the hard way. I create a new project the standard way with react-native init MyAwesomeProject

The Easy Way

Here is a step by step account of implementing react-navigation and dealing with all the errors that occur. I’m following the official setup guide in the docs.

  1. After creating a React Native project we install react-navigation
# Install the latest version of react-navigation from npm
npm install --save react-navigation

However, this will install react-navigation@0.0.0 — i.e. a faulty install.

Speaking from experience, beginners won’t notice this and will proceed to get UnableToResolveError when compiling. I talk about this error further down.

2. To properly install react-navigation you have to explicitly specify the version number. This is found in the right-hand column on their NPM page. At the time of writing it is 1.0.0-beta.9

3. Run npm install again with the specific version

npm install --save react-navigation@1.0.0-beta.9

4. Create a new file router.js to define your routes.

You now have your choice of different navigators. I’ll stick to TabNavigator as it’s basic enough.

Tabs are these things

5. Define your routes in your router

import { TabNavigator } from 'react-navigation';
import MainScreen from '../screens/MainScreen'
import SetupScreen from '../screens/SetupScreen'
export const Tabs = TabNavigator({
Main: {screen: MainScreen},
Setup: {screen: SetupScreen},
});

6. You can now add this code to the render() method in MainScreen.js

const { navigate } = this.props.navigation;
return (
<Button
title="Go to Setup Tab"
onPress={() => navigate('Setup')}
/>
)

7. Make sure to add the TabNavigator to your root component

import React, { Component } from 'react'
import { Tabs } from './config/router'
export default class App extends Component{
render(){
return <Tabs />
}
}

The code is mostly taken from the react-navigation docs. Also, Spencer Carli explains it all in more detail on YouTube.

The Hard Way

Note: React evolves quickly so these problems might not apply at a later point when you find this guide.

The navigator has definitely been this weeks progress bottleneck and one that I solved mere hours before starting this article. Long story short, I created a summary of all errors and their corresponding fixes:

Unable to resolve module`react/lib/ReactComponentWithPureRenderMixin`

GitHub thread — The temporary fix is go to package.json and replace the react-navigation dependency with:

"react-navigation": "git+https://github.com/react-community/react-navigation.git"

then do npm install to update the dependency, which lead’s us to the next error:

npm WARN unmet dependency

Stack Overflow thread — You need to manually install top-level modules that have unmet dependencies and explicitly specify the version number as done in The Easy Way, step 3.

“Unable to resolve module react-native-maps”… “Module does not exist in the module map or in these directories: /../node_modules

GitHub thread — This is React Native’s equivalent of the Windows Blue Screen. The solution is to just delete all dependencies and re-install.

There are many different cases of this error scattered all over GitHub and StackOverflow. Usually it’s fixed by performing these steps:

  • Delete the node_modules folder - rm -rf node_modules && npm install
  • Reset packager cache — rm -fr $TMPDIR/react-* or node_modules/react-native/packager/packager.sh --reset-cache
  • Clear watchman watches — watchman watch-del-all
  • Recreate the project from scratch

Styling and Flexbox

I’ll finish this article with on a lighter note.

Let’s talk Style. In React Native you define your layout’s style using CSS, except in camel case. So background-color is now backroundColor. This is one of the aspects of React Native which is identical to React. The interesting twist is that your styles are just JavaScript objects. So instead of setting #ids and .classes to your components as you do with CSS, you reference the object directly. Even more interesting is that you can pass styles in an array, where the last style overwrites all previous ones, effectively allowing you to inherit styles.

const styles = StyleSheet.create({
bigblue: {
fontSize: 30,
fontWeight: 'bold',
color: 'blue',
},
red: {
color: 'red',
},
});
// applies the styling defined in bigblue
<Text style={styles.bigblue}>just bigblue</Text>
// applies bigblue, then overwrites color with red
<Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>

This brings us to Flexbox. The answer to “How do we make front-end developers forget their multiplication tables” ?

Flexbox is a new way of defining layout. I won’t go into it too much, because I’ll basically be regurgitating the documentation. But my favorite part is flex and ratios. Let’s look at an example:

WindowA has flex: 1 it will cover 100% of the screen. If WindowB has flex: 2 it will be half the size of A, or a 1:2 ratio (yay math!). This is much easier to visualize. It fundamentally shifts CSS from the classic grid layout to “hey, what if we defined size and position relatively”.

Follow @arvinexplores on Instagram and Twitter for more content.

--

--

Arvin Behshad

travel. self-discovery. storytelling. JS⚛ developer exploring the intersection of art and technology.