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
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
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;
}
}
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);
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);
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
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>
);
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
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;
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);
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
Top comments (0)