Logo

dev-resources.site

for different kinds of informations.

Starting React Native Project in 2022

Published at
12/26/2021
Categories
reactnative
expo
typescript
Author
Vladimir Vovk
Categories
3 categories in total
reactnative
open
expo
open
typescript
open
Starting React Native Project in 2022

Updated to Expo 46.

There are many ways to start new React Native project. Here we will be using Expo CLI because it's easier and it has nice defaults out of the box. Also, we will add TypeScript, ESLint, Prettier, and some custom configurations that will make our development process better.

TLDR You can use one command expo init --template @vladimir-vovk/expo-bare-typescript to create new React Native project with all tools already setup for you (see README for details) or follow instructions below. šŸ¤“

Please refer to official React Native and Expo documentation for more details. šŸ¤©

General setup

We will need several tools before we start.

  1. Node.js.
  2. Git.
  3. Yarn.

Then install Expo CLI with npm install --global expo-cli or yarn global add expo-cli.

Awesome! šŸ‘šŸ» Now we have two options to start new React Native project with Expo CLI: "managed workflow" and "bare workflow". Let's briefly look into each variant further. For more in depth comparison please read the official Expo doc.

Managed workflow

Managed workflow is the easiest way. Use it if you are new to mobile development and want to start developing your project right away without spending much time on setup and learning how to build native binaries for iOS and Android.

  1. Run expo init command.
  2. Type your project name.
  3. Choose blank (TypeScript) template.
  4. Change directory to your project: cd <your-project-name>.
  5. yarn start to start Metro Bundler.
  6. Press i to start the iOS simulator or a to run the Android emulator.

Bare workflow

Use bare workflow if you are already familiar with mobile development or want to use some libraries (native code) that is not supported by Expo.

  1. Run expo init command.
  2. Type your project name.
  3. Choose minimal template.
  4. Change directory to your project: cd <your-project-name>.
  5. Start Metro Bundler with yarn start.

Check React Native Setup Guide to ensure that everything that needed to build binaries is installed on your machine.

Use yarn ios or yarn android commands to build and run the app on the iOS simulator or Android emulator.šŸ“±

Tools

TypeScript

Let's add TypeScript support.

  1. Create an empty tsconfig.json file in your project root: touch tsconfig.json.
  2. Rename App.js to App.tsx: mv App.js App.tsx.
  3. Run yarn start. It will prompt you to install the required dependencies (typescript, @types/react, @types/react-native), and automatically configure your tsconfig.json.

Absolute path imports

To use absolute path imports, e.g. import { ComponentA } from 'src/components/A' (notice path starts with src), we need to add baseUrl and paths parameters to the compilerOptions of tsconfig.json.

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "src/*": ["src/*"]
    }
  },
  ...
}

Also we need to create src/package.json file.

{
  "name": "src"
}

Also, we will need to install the babel-plugin-module-resolver to be able to run our project on web.

ā˜šŸ» You can safely skip it, if you targeting only mobile platforms.

yarn add --dev babel-plugin-module-resolver

Specify the plugin configuration in babel.config.js:

module.exports = function(api) {
  api.cache(true);
  return {
    // ... presets settings goes here
    plugins: [
      [
        'module-resolver',
        {
          root: ['.'],
          alias: {
            src: './src'
          }
        }
      ],
    ]
  };
};

Move App.tsx to src folder

It's good to have all source files in one folder. So let's move App.tsx to src with mv App.tsx src command.

Next we need to fix import inside index.js.

...
import App from 'src/App'
...

Prettier

Prettier is an opinionated code formatter. Let's install it with npm install --save-dev prettier or yarn add -D prettier. We will also need .prettierrc.js config file in the project root.

module.exports = {
  semi: false,
  trailingComma: 'none',
  singleQuote: true,
  printWidth: 100,
  tabWidth: 2,
  useTabs: false,
}

Sort imports

Unsorted imports look ugly. Also, it could be hard to read and add new imports. So why not sort them automatically? We can do it with trivago/prettier-plugin-sort-imports.

yarn add --dev @trivago/prettier-plugin-sort-imports

Add plugin configuration to the Prettier config .prettierrc.js:

module.exports = {
  // ... prettier config here

  importOrderSeparation: true,
  importOrderSortSpecifiers: true,
  importOrderCaseInsensitive: true,
  importOrder: [
    '<THIRD_PARTY_MODULES>',
    // '^(.*)/components/(.*)$', // Add any folders you want to be separate
    '^(.*)/(?!generated)(.*)/(.*)$', // Everything not generated
    '^(.*)/generated/(.*)$', // Everything generated
    '^[./]' // Absolute path imports
  ]

Remove React imports

Starting from React 17 it's now not necessary to import React to use JSX. To be able to use this new feature we need to update babel.config.js (line 4).

module.exports = function(api) {
  api.cache(true);
  return {
    presets: [['babel-preset-expo', { jsxRuntime: 'automatic' }]]
    // ... plugins settings goes here
  };
};

And restart Metro Bundler. Press Ctrl-C to stop it and run yarn start to start Metro Bundler again.

Check code for errors

We can use TypeScript compiler and ESLint for this.

TypeScript Compiler

Let's add new check-typescript script to our package.json.

...
"scripts": {
  ...
  "check-typescript": "tsc --noEmit"
},
...

Now we can run yarn check-typescript command to check our code for errors with TypeScript compiler.

ESLint

ESLint has a lot configuration options and rules. Let's start with Expo eslint-config-universe package.

yarn add --dev eslint-config-universe
yarn add --dev eslint prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser
yarn add --dev eslint-plugin-react-hooks
yarn add --dev eslint-import-resolver-typescript

Add .eslintrc.js config file to the project root.

module.exports = {
  extends: ['universe', 'universe/shared/typescript-analysis', 'plugin:react-hooks/recommended'],
  overrides: [
    {
      files: ['*.ts', '*.tsx', '*.d.ts'],
      parserOptions: {
        project: './tsconfig.json'
      }
    }
  ],
  settings: {
    'import/resolver': {
      typescript: {} // this loads <rootdir>/tsconfig.json to ESLint
    }
  },
  /* for lint-staged */
  globals: {
    __dirname: true
  }
}

Add new check-eslint script to our package.json.

...
"scripts": {
  ...
  "check-eslint": "eslint './src/**/*{js,ts,jsx,tsx}'"
},
...

Now we can run yarn check-eslint command to check our code for errors with ESLint. And yarn check-eslint --fix to fix errors automatically.

Lint script

Let's combine TypeScript and ESLint checks together so we can run both at once.

Add new lint script to our package.json.

...
"scripts": {
  ...
  "lint": "yarn check-typescript && yarn check-eslint"
},
...

Changelog

We can use standard-version tool to generate a changelog, bump the version of app and create a new tag automatically.

How It Works:

yarn add --dev standard-version

Create the .versionrc.js config:

module.exports = {
  types: [
    { type: 'feat', section: 'New features' },
    { type: 'fix', section: 'Bug fixes' },
    { type: 'change', section: 'Changes' },
    { type: 'chore', hidden: true },
    { type: 'docs', hidden: true },
    { type: 'style', hidden: true },
    { type: 'perf', hidden: true },
    { type: 'test', hidden: true }
  ]
}

In this config, we enable the feat, fix, and change commit types. And if you want to enable the other commit types, you can remove the hidden boolean and replace it with the section string and provide a title.

Add new release script to package.json:

...
"scripts": {
  ...
  "release": "standard-version"
},
...

Now when you ready to release, just run yarn release command.

Husky

Husky improves your commits and more šŸ¶ woof!

We will use Husky to check if our commit messages follow the conventional commits rules, run the lint check, format staged code with Prettier and ESLint.

yarn add --dev husky
yarn add --dev @commitlint/config-conventional @commitlint/cli
yarn add --dev lint-staged

Create a config for commitlint with commitlint.config.js file:

module.exports = {
  extends: ['@commitlint/config-conventional']
}

Setup lint-staged with package.json > lint-staged configuration:

...
  "lint-staged": {
    "**/*.{js,jsx,ts,tsx}": [
      "eslint './src/**/*{js,ts,jsx,tsx}' --fix",
      "prettier --write './src/**/*{js,ts,jsx,tsx}'"
    ]
  },
...

Configure Husky, add package.json > prepare script and run it once:

npm set-script prepare "husky install"
npm run prepare

husky install will ensure that every developer using this repo will install Husky Hooks before using the project.

Add pre-commit hook:

npx husky add .husky/pre-commit 'npx --no-install lint-staged'

Add commit message hook:

npx husky add .husky/commit-msg 'yarn lint && npx --no-install commitlint --edit "$1"'

react-native-safe-area-context

A flexible way to handle safe area, also works on Android and Web!

yarn add react-native-safe-area-context
npx pod-install

Wrap your App component with SafeAreaProvider:

import { SafeAreaProvider } from 'react-native-safe-area-context'

function App() {
  return <SafeAreaProvider>...</SafeAreaProvider>
}

And now we can use SafeAreaView component.

SafeAreaView is a regular View component with the safe area insets applied as padding or margin.

What to add next?

Post your favourite tools in comments, press šŸ’– button and happy hacking! šŸ™ŒšŸ»

Featured ones: