Develop React (Native) Apps Like a PRO

In my daily job, I see various codebases and collaborate with a lot of developers from all over the world. I’ve noticed that many programmers don’t pay enough attention to things like code cleanness, tests or typings. All of those things are “optional” in JavaScript so you can develop mobile apps without them, but it’s not the way to go if you’re collaborating with other devs or if your project grows larger. There are a few tools built around React which can help you improve your code quality in no time. I’ll try to briefly describe them here and give you a small boilerplate with all of them combined and set up. You can find the link at the end of this article.

ESlint

ESlint is a very basic tool which provides linting utility for modern JavaScript. It’s very pluggable so you can install it globally on your machine and set it up in your IDE to have real-time checks or just simply attach it to your project. For sure the last approach is better because you can have a version targeted especially for your project and also run this kind of check on continuous integration systems. It’s very simple to start with ESlint. First you need to add it to your project:

yarn add eslint --dev
view raw gistfile1.txt hosted with ❤ by GitHub

NOTE: You can use npm instead.

ESlint requires configuration placed inside .eslintrc file, or under “eslintConfig” property in your package.json. If you don’t want to spend time defining all the rules for your project, I recommend the eslint-config-airbnb package, which contains very good rules for writing good React applications. Here’s how it’s done:

npm info "eslint-config-airbnb@latest" peerDependencies

Now you should see peerDependencies versions listed within a JS object inside your console. Simply replace the hashes in the version and run:

yarn add eslint-config-airbnb eslint@^#.#.# eslint-plugin-jsx-a11y@^#.#.# eslint-plugin-import@^#.#.# eslint-plugin-react@^#.#.# <br>--dev

Within the configuration file, create an “extend” key and add airbnb to an array of extensions, and you’re ready to go!

"extends": ["airbnb"]

<p-bg-col>NOTE: You can override some of the rules from this preset inside your config.<p-bg-col>

Prettier

While ESlint is a great tool to analyze your code and eliminate various bugs and bad code, there is another solution with the power to unify your code style on each file with a single command. Prettier, a great tool released by Christopher Chedeau (@vjeux) and James Long (@jlongster), is an opinionated JavaScript formatter with advanced support for language features from ES2017, JSX, and Flow. It removes all original styling and ensures that all outputted JavaScript conforms to a consistent style. Like ESlint, it has plugins for various IDEs, so you can enable it when saving each file. If you don’t want to do this you can just run a CLI command or hook it to pre-commit. It’s very easy to start:

yarn add prettier --dev

yarn add prettier --dev

When prettier is available in your project you can add a new script to your npm scripts in package.json; the entry could look like this:

"scripts": {
...
"prettier": "prettier — single-quote — trailing-comma all — write "src/**/*.js""
},
view raw package.json hosted with ❤ by GitHub

It tells prettier to format your .js files within the src/folder with some formatting options. You can check the full GitHub docs.

Prettier plays along with ESlint very well — it provides some eslint presets, so if you’re using them both, don’t forget to add extensions, just like you did with the airbnb preset:

yarn add eslint-config-prettier --dev

and then:

"extends": [
"airbnb",
"prettier",
"prettier/flowtype",
"prettier/react"
],

Flowtype

I’ve begun my programming journey with Java. When I moved to web development, I loved the freedom JavaScript gives in everyday development, but I felt like something was missing. Everything was very well typed in Java apps, and when I heard about Flow I was very excited. Static typing helps you eliminate a lot of errors and makes the code really readable for other developers. What’s great about Flow is the fact that it plays along with your IDE in real time, just like ESlint. In React Native the .flowconfig file isalready present in the generated app. You simply have to install flow:

yarn add flow-bin --dev

To perform typecheck in your app just add the script to your package.json

"scripts": {
...
"flow": "flow",
},

Then you can run:

yarn run flow
view raw yarn run flow hosted with ❤ by GitHub

If you want to add Flow to your web application you have to specify .flowconfig by yourself. But don’t worry — it’s super easy, just follow the Flow docs and read the article about the configuration.

Haul

If you haven’t heard about it yet, Haul is an open-source library which is a replacement for react-native packager. It allows you to access a full webpack ecosystem, so things like aliases or symlinks are easily doable. To get more info about what’s possible with Haul, please check the haul repo and the webpack docs. I’ll quickly show you how to add Haul into your project and set some aliases to avoid relative paths and make your code a bit more readable for other developers. First, you need to add haul into your project:

yarn add haul --dev

NOTE: It used to be haul-cli until June 2017.

From now on you can run the haul init script:

yarn run haul init

Notice that there is a new file called webpack.haul.js generated within your project. It provides a hook which allows you to mutate Haul’s default webpack config. There are tons of options to customize your project with webpack. I’ll show you real quick one of my favorite options, which are aliases for directories in your project. Open your webpack.haul.js and edit the exported function:

const path = require(‘path’);
module.exports = ({ platform, root }, defaults) => ({
entry: `./index.${platform}.js`,
resolve: {
...defaults.resolve,
alias: {
...defaults.resolve.alias,
components: path.join(root, 'src', 'components'),
containers: path.join(root, 'src', 'containers'),
stores: path.join(root, 'src', 'stores'),
routes: path.join(root, 'src', 'routes.js'),
}
}});
view raw webpack.haul.js hosted with ❤ by GitHub

In this specific case, I created aliases for components, containers, and stores directories and to the routes file.

Now within your project, you can import components like this:

<strong>import</strong> Button <strong>from</strong> 'components/Button';

Amazing, isn’t it?

If you’re using Flow inside your project, aliases will produce an error. If you want to get rid of it, you need to specify module.name_mapper in your .flowconfig options. The module name mapper definition for our aliases should look like this:

module.name_mapper='^components/(.*)'->'<PROJECT_ROOT>/src/components/1'
module.name_mapper='^containers/(.*)'->'<PROJECT_ROOT>/src/containers/1'
module.name_mapper='^stores/(.*)'->'<PROJECT_ROOT>/src/stores/1'
module.name_mapper='^routes'->'<PROJECT_ROOT>/src/routes.js'

No errors! Yay!

UPDATE: Recently, we've refreshed and add new features to Haul. As it was a major update, we decided to rename the library to Re.Pack. Check out its webpage to see what's new!

Also, we've prepared an episode of The React Native Show podcast fully dedicated to Re.Pack in which Paweł Trysła, the lead engineer at Re.Pack (previously Haul) dives into details of this library. You can watch it here:

Jest

Testing is very important to ensure your code quality. When it comes to testing React components, Jest is my first call. It’s already bundled with the RN initial project, so you don’t have to install anything. With snapshot testing, you can cover a nice amount of your code without writing a lot of code in your test files. Look how simple wring a test for the component is:

/* @flow */
import React from 'react';
import renderer from 'react-test-renderer';
import Button from '../Button';
describe('<Button />', () => {
it('should render correctly', () => {
const tree = renderer.create(<Button />).toJSON();
expect(tree).toMatchSnapshot();
});
});
view raw JEST hosted with ❤ by GitHub

If you want to learn more about snapshot testing check out this great Callstack article.

Other tools

There are a lot of other tools and libraries to help you increase your app development skills. I put everything you read today and some other cool libs inside an example app. If you want to learn more about other tools, check how to write React Native apps with MobX.

Mike.

Insights

Learn more about Developer Experience

cover

May 5Article

Codex Ambassador: Q1 Recap Across 5 Cities

A short recap of Codex events in Berlin, Wroclaw, Warsaw, Sopot, and Miami, plus what we learned from each format and where we want to go next.

cover

Feb 5Live Stream

Storybook Explained: From Basics to Advanced Workflows

Core Storybook concepts, stories and args, interaction testing, and how Storybook works in React Native projects.

cover

Jan 29Article

Announcing AI SDK Profiler for React Native

Announcing the AI SDK Profiler plugin for Rozenite DevTools. Capture OpenTelemetry spans from the Vercel AI SDK and inspect AI requests across on-device and cloud providers.

cover

Nov 28Talk

How I Hacked React Native DevTools (And Built a Plugin Framework)

Learn how React Native DevTools work under the hood, and how to inject custom plugins with clean hooks and no forks.

cover

Sep 16Talk

How I Hacked React Native DevTools (And Built a Plugin Framework)

Learn how React Native DevTools work under the hood, and how to inject custom plugins with clean hooks and no forks.

cover

Jul 28Article

Introducing Rozenite: A Plugin Framework for React Native DevTools

Build custom debugging panels inside React Native DevTools with Rozenite: a modular, TypeScript-ready plugin framework with full device-scoped support.

cover

Feb 12Article

How to Easily Create Native Libraries With Nitro and Turbo Modules

Learn how to optimize React Native performance with Turbo and Nitro Modules. Ditch the legacy bridge and master modern native module development.

cover

Dec 4Podcast

Radon IDE: Better Developer Experience for React Native Teams

Find out how Radon IDE can help increase team velocity and rid you of the common React Native app development pain points.

cover

Sep 19Podcast

Exploring Bun: Jarred Sumner on Hyperfast JavaScript Toolkit

Is Bun the future of React Native package management? Join us as we talk with Jarred Sumner, the creator of this lightning-fast JavaScript toolkit.

cover

Sep 11Podcast

Vim: from Zero to Hero

Discover the power of Vim, the legendary text editor, as we explore its origins, standout features, and practical tips to boost your coding efficiency.

cover

May 15Article

Add-Ons for Web Browsers With React

At times you may need to create an add-on to use a web browser more effectively. Find out how to build one with React.

cover

Jan 27Article

Why Is It Worth to Automate Your Dependency Management with `Autolinking`?

When you automate your dependency management, you can fully focus on developing your app. Find out how you can do it with autolinking.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

Writing a Swift TurboModule in React Native

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.