React Native starter project

A quick guide on how to set up a starter project so you don’t have to deal with the installation and setup of libraries you always need.

Jaka Tertinek
CodeX

--

You can find the project on GitHub.

This article is a work in progress and will be updated shortly. Currently, we have setup:

  1. DONE: Initialise the project with react-native init,
  2. DONE: Add Typescript support
  3. DONE: Create basic project structure and add React Navigation support
  4. TODO: Redux support
  5. DONE: SVG image support
  6. DONE: Secure storage support

Does this sound familiar. You have a great idea that you want to test out. After a while of programming, you realise how much time is going to take before you have the basics set up. You lose your interest and decide to continue working on the project some other time.

Well if you are like me, this has happened to you more than once. I decided enough is enough it’s time to deal with this problem once and for all. Let’s create a starter project which has everything you need to start developing your idea right away. So what do we need? We need some sort of navigation and state management. Let’s also add .svg picture support, Typescript and encrypted storage for securing login tokens.

1. Using react-native init <<PROJECT NAME>> to initialise our project

There is no need to reinvent the wheel here, let us use react-native init to initialise our project. It creates a basic working application that has one home screen.

react-native init starter_project
Project structure after running react-native init
Image 1: Project file structure after running react-native init.

2. Installing Typescript and React Navigation

There is no need to install Typescript after project initialization. You can use the Typescript template provided by react-native (more on that here ). The issue with that lies in that you always have to check if the versions of the template are up to date plus it adds code that we do not need. So It’s best to add Typescript yourself. This can be achieved very easily in 3 steps.

  1. Navigate to your project in terminal (or cmd) and run the following command:
npm install -D typescript @types/jest @types/react @types/react-native @types/react-test-renderer

2. Add a TypeScript config file. Create a tsconfig.json at the root of your project:

{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"isolatedModules": true,
"jsx": "react",
"lib": ["es6"],
"moduleResolution": "node",
"noEmit": true,
"strict": true,
"target": "esnext"
},
"exclude": [
"node_modules",
"babel.config.js",
"metro.config.js",
"jest.config.js"
]
}

3. Create a jest.config.js file to configure Jest to use TypeScript

module.exports = {
preset: 'react-native',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
};

You can find a more in-depth explanation of these steps on the official React Native website.

3. Creating a basic project structure and adding React Navigation

How a React Native project should be structured is a hot debate that has been going since its first release. There was some interest in adapting common architecture patterns, like MVC (Model — View — Controller), that didn’t make much sense at the end and increased the complexity of an application without significant benefits.

Image 2:Basic structure of a source folder.
Image 2:Basic structure of a source folder.

What I like to do is a basic project structure consisting of folders: “assets”, “components”, “redux”, “screens” and “utils”. The names together with what the folders contain is self-explanatory but for those that are just starting here is a brief explanation:

  • assets: contains all your static files like pictures, fonts colours and global styles.
  • components: contains separate folders for every component type. For example, you can create folders for your buttons, alerts, modals, inputs …
  • redux: houses logic for redux state management. Is further divided into folders for your actions and reducers,
  • screens: contains your main screen/view logic
  • utils: includes files for database management, API management, support function and so on…
3: Example how a source folder might look like after application is developed.
Image 3: Example of how a source folder might look like after the application is developed.

In Image 2 you can see that we have a file called “navigator.tsx”. This is down to preference but I like to have one file that contains all the navigation inside the application. React Native already has a built-in navigator library for navigating mobile applications but it’s very rarely used. The go-to libraries are React Navigation and react-native-navigation. Both do the job fine, but there are some differences. It’s up to you to decide which one you like better and find it easier to use. For me, the clear winner is React Navigation. Mostly because of its ease of use.

To install React Navigation run the following command:

npm install @react-navigation/native @react-navigation/stack react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view

This installs React Navigation together with Stack navigator (react-navigation/stack) and all of its many dependencies. Depending on your case you might also need tab navigator and/or a drawer navigator. Given this is just a starter project we don’t have anything more than the stack navigator.

Now that we have installed everything related to navigation let’s write some code. I’m not going to go into detail and explain how React Navigation works and what parts of the code mean. There are more detailed articles out there.

In the following snippet, you can see how we imported “Home screen” and then created a “HomeStack” and main “Navigator”. You can add multiple screens to the HomeStack or create a separate stack for login/registration screens.

I suggest that you create your own screen template that contains everything that you might need or like to use (class components for example instead of functional components)

4. Adding support for SVG images

If you are interested in learning more about adding support for SVG images you can check out this article.

To add support for SVG images run the following command:

npm i react-native-svg react-native-svg-transformerand cd ios && pod install

This installs react-native-svg(allows the displaying of images) and react-native-svg-tranformer (allows you to import SVG files in your project).

Just installing a transformer by itself will not automatically transform SVG images to PNGs when building the project. We need a way to tell the compiler to transform the images. We do this by adding or modifying our metro.config file.

const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
const {
resolver: { sourceExts, assetExts }
} = await getDefaultConfig();
return {
transformer: {
babelTransformerPath: require.resolve("react-native-svg-transformer")
},
resolver: {
assetExts: assetExts.filter(ext => ext !== "svg"),
sourceExts: [...sourceExts, "svg"]
}
};
})();

If we try to import an SVG file into a TSX file we will get an error. This is an indication that the project is missing a declaration file.

Open your declaration.d.ts file or create it and add support for SVG files. This way you won’t get errors when import SVG images into a TypeScript file.

declare module "*.svg" {
import React from 'react';
import { SvgProps } from "react-native-svg";
const content: React.FC<SvgProps>;
export default content;
}

5. Adding secure storage for storing user login information

If you are interested in learning more about different possibilities for securely storing data you can check out this article.

What information should be stored permanently on the phone depends on each use case. What we can say with certainty is that if we have a login functionality build into our application we have to store some information about the authenticated user. This usually includes a user ID, user email/username and a token or ID used for communicating with the back-end. This way our backend knows that the user was already authenticated.

There are quite many libraries that can be used. For example, there are react-native-keychain and react-native-encrypted-storage. At the end of the day, all of them use the same native functionalities to achieve the goal (iOS-Keychain Services and Android-Shared Preferences). Which one to use comes down to personal preference. My personal favourite is react-native-encrypted-storage, but I encourage you to check out the others as well.

npm i react-native-encrypted-storageandcd ios && pod install

The easiest way to manage data is to create a gateway. In general, we only need three simple functions that help us to save, load and remove data. It works pretty much the same as AsyncStorage. Keep in mind that “user_session” in the example is the key with which we access data. It can be anything you want.

--

--

Jaka Tertinek
CodeX
Writer for

I’m a software developer trough and trough. I worked with mostly React Native and Node.js. Currently, I’m working as a CTO for a small startup.