Pro tips for setting up a React Native project in 2020


The year is 2020 and mobile development is still in an upturn. For smaller businesses native mobile development is not an option most of the time because it requires a lot of time and developer resources so it is not cost effective enough. Luckily, React Native, Facebook’s mobile cross platform development tool have improved a lot in the past years and it can be a viable option instead of pure native mobile development.

In this article I will discuss the following topics:

  • Motivation
  • Project bootstrapping
  • Initial directory and file changes
  • Explicit build tool and dependency versions
  • Code formatting and linting
  • Absolute imports and modularization
  • Grouped exports
  • Final thoughts


Personally, I like to plan ahead, I’m convinced that if a project builds on a solid base then it will stand the test of time. Whenever I start working on a project, I always assume it is a long running one, meaning I try to prepare for whatever might happen but without being prophetic.

As at Supercharge I had the opportunity to successfully ship multiple React Native projects and support them for years in production, I would like to share with you some tips on how I would bootstrap a new React Native project nowadays.


Other than the React Native requirements, I recommend installing Node Version Manager (MacOS, Linux, Windows), NodeJS 8.17.0 or newer, Node Package Manager 5.2 or newer, and Visual Studio Code with ESLint and Prettier extensions.

Project bootstrapping

I always use the React Native CLI to create a new React Native project, because in the long term there’s a great chance that I have to write some native (Android, IOS) code.

So let’s create our new React Native project called MyApp:

npx react-native init MyApp --template react-native-template-typescript --npm
  • NPX is a package runner for NPM, and it’s available since NPM 5.2. With NPX there’s no need to install the ‘react-native-cli’ package globally just to initialize our project.
  • The ‘ — template react-native-template-typescript’ parameter will use the Typescript template to create the project. I always use Typescript for static type checking, it will make things more developer friendly and less prone to errors.
  • The ‘ — npm’ parameter will make the project use NPM instead of Yarn to install initial dependencies.

Initial directory and file changes

I like to move all of the project javascript source files to an ‘src’ directory to keep the project root nice and tidy. Then I move the ‘App.tsx’ file from the project root to the ‘src’ directory. Finally, because we’re using Typescript in the project, I rename the ‘index.js’ file to ‘index.ts’.

Explicit build tool and dependency versions

It’s important to make project builds repeatable, no matter where the project is built (CI, other developer’s machine). That’s why I like to use explicit build tools, package manager and dependency versions wherever possible.

To use explicit Node and NPM versions, some changes need to be made:

Update package.json file with ‘engines’ block:

"engines": {
"node:": "x.y.z",
"npm": "a.b.c",
  • Where “x.y.z” is the explicit Node version you want to use (Eg: “12.16.1”)
  • Where “a.b.c” is the explicit NPM version you want to use (Eg: “6.13.4”)

Create a .npmrc file in the project root directory with the following content:

  • The ‘engine-strict=true’ line will make NPM look for allowed version defined in the “engines” block when I am trying to install dependencies
  • The ‘save-exact=true’ line will make NPM install explicit dependency versions. You’re correct to think that’s why we have the ‘package-lock.json’ file, but I like to see explicit dependency versions in the package.json file as well.

Code formatting and linting

The consistent code style is really important when multiple developers contribute to the project. To make code formatting become nothing to worry about, I use Prettier, which takes the burden off my shoulders.

There’s a ‘.prettierrc.js’ file in the project root already, but we can customize it further. In my case I use the following Prettier config:

module.exports = {
tabWidth: 2,
useTabs: false,
printWidth: 140,
semi: true,
trailingComma: 'es5',
bracketSpacing: true,
arrowParens: 'always',
singleQuote: true,
jsxSingleQuote: true,
jsxBracketSameLine: true,

To make code formatting an automatic task on save, I populate the workspace config file of Visual Studio Code (.vscode/settings.json) with the following content:

"editor.tabSize": 2,
"editor.formatOnSave": false,
"[javascript]": {
"editor.formatOnSave": true
"[typescript]": {
"editor.formatOnSave": true
"[javascriptreact]": {
"editor.formatOnSave": true
"[typescriptreact]": {
"editor.formatOnSave": true
"typescript.tsdk": "node_modules/typescript/lib"

As I prefer single quotes in the source files, I add rule override to the ‘.eslintrc.js’ file to not to warn me about single quotes:

module.exports = {
root: true,
extends: '@react-native-community',
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
overrides: [
files: ['*.js', '*.ts', '*.jsx', '*.tsx'],
rules: {
'jsx-quotes': 0,

As a final step, I add linting scripts to the package.json file:

"scripts": {
"lint:style”: "prettier --check 'src/**/**.{js,ts,jsx,tsx}'",
"lint:code": "eslint src/ --ext .js,.jsx,.ts,.tsx",
"lint": "npm run lint:style && npm run lint:code",
"test": "jest",
"sanity": "npm run lint && npm run test"

Absolute imports and modularization

I don’t like long relative imports when I’m deep in the directory tree. It makes refactoring circumstantial. In order to avoid this, I always modularize the codebase based on some logic and use absolute imports in the source files.

First, let’s create the following directory and file structure:


By creating package json files in the sub directories, I define sub-modules. Let’s populate the contents of the package.json files:


"name": "app"


"name": "core"


"name": "ui"

To be able to use absolute imports, I need to update the tsconfig.json file in the project root:

"compilerOptions": {
"baseUrl": "./src",

After these changes we can use import statements the following way:


Import { Row } from 'ui/component/layout/Row.component.tsx'
Import { someExportedUtilMethod } from 'core/util/utils.ts'

To avoid circular imports and keep the separation of concerns intact, there are some important rules to pay attention to:

  • Files under any sub-module directory should use relative imports when importing from files under the same sub-module directory
  • Files under the ‘app’ directory should import from files under the ‘app’, ‘core’ and ‘ui’ directories
  • Files under the ‘core’ directory should only import from files under the ‘core’ directory
  • Files under the ‘ui’ directory should import from files under the ‘ui’ and ‘core’ directories

Grouped exports

When named exports are used instead of default exports, they can be grouped in index files which then can be used to import the named exports from. The advantage of this is that files can be moved freely under a given root directory and there is no need to update every single source file where these files are used to import from.

First, I have the following directory and file structure:



export * from './FlatButton.component';
export * from './RaisedButton.component';


export * from './Column.component';
export * from './Row.component';


export * from './button';
export * from './layout';

After I’ve populated the index files, I can use imports the following way:


import { Column, FlatButton, RaisedButton, Row } from ‘ui/component

This way I don’t have to explicitly define the path for the import, I can move the components under the component directory freely, I only have to update the related index files.

Final thoughts

I hope this bootstrapping guide will be helpful for you in the future when starting a new React Native project.

Remember, nothing is written in stone, these are just suggestions based on my own experience with React Native.

Thanks for reading it through, I welcome any feedback regarding this topic.

At Supercharge, we are a next-generation innovation agency working with our clients to create transformative digital solutions. If you liked this article, check out some of Supercharge’s other articles on our blog, or follow us on LinkedIn, and Facebook. If you’re interested in open positions, follow this link.




As innovation partners, Supercharge works with clients to create transformative digital solutions. We create digital strategies, design delightful interfaces and build robust software. We are happy to share with you what we learn on this journey.

Recommended from Medium

Let’s Clear Up the Most Confusing Thing in CSS

computer screen showing CSS

Backend-Only Authentication With Sapper & Firebase Admin

Svelte for Angular Developers

Node.js Development Preparation

npm weekly #140: How we rebuilt,

NodeJS — Run your app with multiple versions of Node

Getting Familiar with Canvas: Code Along!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tamás Menyhárt

Tamás Menyhárt

More from Medium

Login With Regex Expo React Native

Expo React Native Login Navigation

How to setup React Native and create a simple To-Do App

Using Redux to Build a Recipe App

How to reuse or adapt React components in React Native using WebView on Android?