Updated to Expo 47.
There are many ways to start a new React Native project. Here we will be using Expo's create-expo-app command line tool because:
- It has nice defaults out of the box.
- It is compatible with Expo packages, which are usually very good, well-tested, and have excellent documentation.
- We can easily switch to a "bare" react-native app at any moment with one
npx expo eject
command. See the docs to learn about the difference between managed and bare workflows.
Also, we will add TypeScript, ESLint, Prettier, and some custom configurations that will make our development process better.
TLDR You can use one command
npx create-expo-app -t expo-ts
to create new React Native project with all tools already setup for you (see README for details) or follow instructions below. π€
Please refer to the official React Native and Expo documentation for more details. π€©
General setup
We will need Node.js, Git and Yarn before we start.
Please check React Native Setup Guide to ensure that everything is installed on your machine.
Awesome! ππ»
Now let's create a new app.
- Run
npx create-expo-app
command. - Type your project name.
- Change directory to your project with
cd <your-project-name>
command. - Run
yarn start
to start Metro Bundler. - Press
i
to start the iOS simulator ora
to run the Android emulator.π±
Tools
TypeScript
Let's add TypeScript support.
- Create an empty
tsconfig.json
file in your project root:touch tsconfig.json
. - Rename
App.js
toApp.tsx
:mv App.js App.tsx
. - Run
yarn start
. It will prompt you to install the required dependencies (typescript
,@types/react
,@types/react-native
), and automatically configure yourtsconfig.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/*"]
},
"strictNullChecks": true
},
...
}
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 create a new App.js
file inside our project's folder with touch App.js
. And import our app logic there:
import App from 'src/App'
export default () => <App />
Prettier
Prettier is an opinionated code formatter. Let's install it.
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
]
}
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:
- Follow the Conventional Commits Specification in your repository.
- When you're ready to release, run
standard-version
.
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"'
SafeAreaContext
react-native-safe-area-context provides a flexible API for accessing device safe area inset information.
npx expo install react-native-safe-area-context
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 regularView
component with the safe area insets applied as padding or margin.
What to add next?
- React Navigation.
- Async Storage or Secure Storage.
- Watermelon DB.
- Tests with Jest and React Native Testing Library.
Credits
You can find the π΄π» 2022 version here.
Please post your favorite tools in the comments, press π button, and happy hacking! ππ»
Top comments (0)