Build an React Native app. Part 1: Development

andreasbergqvist

Andreas Bergqvist

Posted on February 19, 2020

Build an React Native app. Part 1: Development

At Itiden we build web applications and mobile apps.
For both we really enjoy using React & React Native.

This blog post is a informational post to my talk at React meetup in Gothenburg in two parts:

Build an React Native app. Part 1: Development (this)
Build an React Native app. Part 2: Distribution

We have open sourced an React Native app called "Guess the Repo" that uses the libraries we have decided on. It's a quiz app with questions about Github repos. Read more about the app on https://guesstherepo.itiden.se.

It's not in anyway a spectacular app. But it's quite easy to get up and running if you would like to see how an React Native app can be done.

Development

This is a general overview of how we have decided to use React Native and what libraries we use. Generally we have settled with what we think is enjoyable, effective and what seems to be well maintained, documented and updated by the community.

React Native cli

While there are other alternatives then using the React Native cli to initialize you new project. We have currently decided to use it for our projects.

We are also using TypeScript and unlike a few years ago, it's really enjoyable to use with React Native apps.

Code to initialize your new app:

npx react-native init GuessTheRepo --template react-native-template-typescript
Enter fullscreen mode Exit fullscreen mode

State management

For global state management we have decided on MobX. It's really efficient and makes your code really easy to read and to follow.

Add to your project with:

yarn add mobx
         mobx-react
         mobx-persist
Enter fullscreen mode Exit fullscreen mode

Notice that we add both mobx and mobx-react but also mobx-persist. It's an really convenient library to use if you like to keep some of your state persisted between app restarts.

Example store:

import {observable, action} from 'mobx';
import {persist} from 'mobx-persist';

export default class QuizStore {
  @persist
  @observable
  score: number = 0;

  @action
  addScore() {
    this.score += 1;
  }
}
Enter fullscreen mode Exit fullscreen mode

This creates a store with a score value that will be persisted. We also add an addScore action to add 1 to the score.

When you create the store, add the following code to make it use AsyncStorage as peristing storage:

import {create} from 'mobx-persist';

const quizStore = new QuizStore();
const hydrate = create({
  storage: AsyncStorage, 
  jsonify: true
});
hydrate('quizStore', quizStore);
Enter fullscreen mode Exit fullscreen mode

Now, the score value will be kept even if the app is closed.
To use the score value or use the action method from an component, see the following code (notice that we created the store in an Context that we can get from a useQuizStore() function):

import {observer} from 'mobx-react';
import {useQuizStore} from '../context/AppContext';

const QuizScreen = () => {
  const quizStore = useQuizStore();
  return (
    <View>
      <Text>Score {quizStore.score}</Text>
      <Button onPress={() => quizStore.addScore()}>Button</Button>
    </View>
  );
};

export default observer(QuizScreen);
Enter fullscreen mode Exit fullscreen mode

Don't forget to "wrap" your component in the observer function (HoC) to make sure the component re-renders when an value from the MobX store updates.

Styling

When it comes to styling we have decided on styled-components. It's enjoyable, efficient and creates really readable code. And it works really well for both React and React Native.

Add it to your project:

yarn add styled-components
         @types/styled-components
Enter fullscreen mode Exit fullscreen mode

Notice that the TypeScript typings needs to be fetched from the @types repo.

When using styled-components with React Native you need to use the /native library.

Example on using it:

import styled from 'styled-components/native';

const Background = styled.TouchableOpacity`
  border-radius: 20px;
  background-color: #000000;
  padding: 10px 20px;
`;

const Label = styled.Text`
  font-size: 24px;
  color: #fff;
`;

interface ButtonProps {
  label: string;
  onPress: () => void;
}

export const Button = (props: ButtonProps) => (
  <Background
    onPress={props.onPress}       
  >
    <Label>{props.label}</Label>
  </Background>
);
Enter fullscreen mode Exit fullscreen mode

Navigation

For navigation react-navigation has come a real long way since v1. Now at version 5 we have a completely new declarative way of declaring our navigation routes.

First, a bunch of libraries are needed:

yarn add @react-navigation/native
         @react-navigation/stack
         react-native-gesture-handler
         react-native-reanimated
         react-native-screens
Enter fullscreen mode Exit fullscreen mode

All of these are not needed, but the @react-navigation/stack is commonly used navigation type. And react-native-gesture-handler and react-native-reanimated dependencies needed for performant animations and gestures. The react-native-screens make even more use of native views when the different routes are created making it even more performant.

Read more on getting started with React Navigation on their docs.

Example of setting up your routes:

import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import React from 'react';
import HomeScreen from './screens/Home';
import QuizScreen from './screens/Quiz';

const Stack = createStackNavigator();

const Routes = () => (
  <NavigationContainer>
    <Stack.Navigator>
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Quiz" component={QuizScreen} />
    </Stack.Navigator>
  </NavigationContainer>
);

export default Routes;
Enter fullscreen mode Exit fullscreen mode

When creating components you can now do the following to link to other routes:

import {useNavigation} from '@react-navigation/native';

const HomeScreen = () => {
  const navigation = useNavigation();
  return (
    <View>
      <Button label="Navigate!" onPress={() => navigation.navigate('Quiz')} />
    </View>
  );
};

export default observer(HomeScreen);
Enter fullscreen mode Exit fullscreen mode

These are some of the "building blocks" used to create an React Native app.

Next up I'll show how you can distribute your app with App Center from Microsoft.
Build an React Native app. Part 2: Distribution

For some more inspration, check out William Candillon's "Can it be done in React Native?" youtube channel! https://www.youtube.com/channel/UC806fwFWpiLQV5y-qifzHnA

💖 💪 🙅 🚩
andreasbergqvist
Andreas Bergqvist

Posted on February 19, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related