9

Essential Tools for Improving React Native Development

React Native is a framework with a very strong developer community. During the last year, there was an evolutionary growth of a large variety of tools and libraries, making the development of React Native apps a lot easier and a lot more comfortable.

Besides the tools and libraries developed especially for React Native, you can also use a lot of things in the plain React ecosystem. This is because most of these things are compatible with the JavaScript/React part of any React Native app.

Being aware of the best tools and libraries and how to use them is really useful because it saves you a lot of time and can greatly improve the quality of your code and product.

Especially when you are working on bigger projects, some tools are an absolute must-have to ensure good collaboration in a bigger team.

In this chapter, you will learn about the following topics:

  • How to improve code quality with type safety, linters, and code formatters
  • Why and when you should use boilerplate solutions and how to leverage them
  • How to find and use high-quality UI libraries
  • Why and when you should use Storybook and how to use it

Technical requirements

To be able to run the code in this chapter, you have to set up the following things:

Improving code quality with type safety, linters, and code formatters

As already mentioned in Chapter 2, Understanding the Essentials of JavaScript and TypeScript, it is necessary to use typed JavaScript alongside some tools to ensure a certain level of quality in bigger projects.

In the following section, you will learn how to do this. Let’s start with type safety using TypeScript or Flow.

Ensuring type safety with TypeScript or Flow

Type safety is standard in most programming languages such as Java or C#, and this is for good reason. In contrast, JavaScript is dynamically typed. This is because of the history of JavaScript. Remember, JavaScript was created as a scripting language to write small chunks of code very quickly. For this scenario, dynamic typing is fine, but when a project grows, static typing with all its advantages is a must-have.

Using typed JavaScript creates some overhead for creating your types at the beginning, but it gives you a lot of advantages at the end. Also, today, most libraries come with defined types, which you can use out of the box.

In Chapter 2, Understanding the Essentials of JavaScript and TypeScript, you already learned how to use and write TypeScript. This subsection focuses on the advantages of TypeScript and what errors you can prevent when using it.

Dynamic typing can lead to serious and hard-to-find errors

Let’s start this section with a real-world example, which I experienced in one of my projects. While working on a React Native project, we used JavaScript without static typing. We fetched questions with a unique ID from a remote database (Google Firebase) and stored them locally on the device (AsyncStorage).

Based on the ID of the questions, we also stored user answers and marked the questions as answered in the app. After an update, all the answers seemed to be gone from the users’ devices, and nobody understood why. It turned out that the update changed the unique IDs from number to string, which made the comparison between the stored user answers and the questions fail.

The debugging of this error was very hard because it didn’t occur when answers were created with the updated version of the app. It only occurred when questions were answered in an older version of the app; following this, the app was then updated, and the questions were synced.

In addition to that, the error never threw an error message. It just happened silently. So, it took quite some time to find and fix the bug. This is just one example of an error that happens because of dynamic typing and why it is hard to deal with these errors. They can lead to hard errors, which you notice directly, but in a lot of cases, they don’t.

This is especially severe in the case of app development, where you store a lot of data on the users’ devices. When you don’t realize that you have problems with your data types, this can lead to corrupt data on millions of different devices, which is really hard to recognize, debug, and fix.

Most of these errors can be prevented with static type checking using TypeScript or Flow.

Important note

When using TypeScript or Flow, don’t use any or Object to make your life easier while writing your types. Type checking and all its advantages only really work when using it in the whole project. So, you should explicitly type all your properties.

Typed JavaScript doesn’t only prevent bugs, it can also boost your productivity.

Enhancing your IDE with code completion

When you have statically defined types, it is easy for your IDE to help you with code completion. Most modern IDEs such as Visual Studio Code or JetBrains WebStorm have excellent support for TypeScript and Flow.

While WebStorm has most of the support built in for TypeScript and Flow, there are a lot of useful plugins for VS Code. Especially when working with Flow, you must install an extension for code completion and code navigation to work correctly. To do so, go to Extensions and search for Flow Language Support.

Additionally, I would recommend running type checks in every commit with your CI pipeline. You can read more about this in Chapter 11, Creating and Automating Workflows.

While typed JavaScript prevents a lot of errors and boosts productivity, there are many more areas where you can prevent errors from happening. Most of them are covered by linters. In the next section, you learn what they are and how they work.

Getting rid of the most common bugs with linters

Linters are tools that watch your code and enforce certain rules. When it comes to JavaScript/TypeScript, ESLint is, by far, the most popular and mature linter on the market, so this subsection will focus on ESLint. It analyzes your code and finds problems by checking your code against a predefined ruleset.

These problems can be errors, non-efficient code, or even code styling errors. I would recommend using ESLint because it comes at no cost and can ensure a certain level of code quality.

If you use the React Native CLI to set up your project, you will find ESLint preinstalled with a working ruleset. If you want to add it to an existing project, you can install it with the following commands: either use npm install –-save-dev eslint or yarn add –-dev eslint. In the next step, you have to set up a configuration. This can be done automatically with the npm init @eslint/config or yarn create @eslint/config commands.

Now you can use ESLint to check your code against your ruleset with npx eslint file.js or yarn run eslint file.js. ESLint even comes with a --fix option, which automatically tries to fix as many errors as possible.

You can also integrate ESLint in most modern IDEs, to highlight and automatically fix problems found by ESLint. I would recommend doing so.

Additionally, I would recommend running ESLint checks in every commit with your CI pipeline. You can read more about that in Chapter 11, Creating and Automating Workflows.

ESLint is an awesome tool to find common errors, and even though it also supports code styling rules, there is another tool that does a better job in this area.

Enforcing a common code style with prettier

Prettier is a code formatter that was created in 2016. Essentially, it automatically rewrites your code based on a set of rules. This ensures that it follows standards and enforces a common code style for the whole development team of a project.

To use prettier, you can simply install it as a development dependency with the following commands. Either use npm install --save-dev prettier or yarn add --dev prettier.

It can be a bit challenging to integrate prettier with linters such as ESLint. This is because – as you learned in the previous subsection – these linters also have rules to format code. When you use both and have specified conflicting rules, this won’t work. Fortunately, prettier comes with premade configs for ESLint, which prevent exactly that. You can download them from the prettier home page.

After the installation is complete, you can run prettier from the command line. To check whether your code styling follows the prettier rules, you can use the prettier command, followed by the path of a file or folder you want to check. In practice, you often want to make prettier format your files for you. This can be achieved with prettier --write followed by a path of a file or folder.

Important tip

You can use a .prettierignore file to exclude files from getting rewritten by prettier. You should use this file to prevent rewriting of files that are not written by you, config files, or others.

Prettier brings a lot of value to your project, and you will not want to develop without it, especially when you are not working alone. The most important advantages of using prettier are listed as follows:

  • Easier code reviews: When doing code reviews, most editors highlight the changes that have been made. By far, the most annoying thing in a code review is when a developer has another autoformatting setting, resulting in all the code being marked as changed for the review. While this makes total sense because all the code has been changed due to autoformatting, it makes the review process a lot harder. It takes more time and makes it more vulnerable to errors in the review. Prettier prevents this by enforcing a common code style.
  • Easier code readability: When you add developers to your team, code readability is an important factor. The easier the code readability is, the less time a new developer will need to be a productive part of your team. Prettier guarantees a common code style, which makes the code easier to read and understand.

Prettier is available as a command-line tool and as an IDE extension/plugin for all common IDEs. To ensure that it is used, you should include it in the following parts of your project:

  • IDE: All developers should add prettier to their IDE and configure their autoformatting shortcut to use prettier.
  • Before Commit: A before commit hook should ensure that prettier does not throw any errors.
  • CI/CD: When creating a pull request/merge request, prettier should be run to ensure that the manual review can be done in an efficient manner. You can read more about this in Chapter 11, Creating and Automating Workflows.

If you implement this process with prettier, you will save a lot of time in the long run.

So, you learned about the most important tools while working with React Native projects. Now you will get to know some tools to successfully start new React Native projects. There are different open source boilerplate solutions on the market, all with their own advantages. A boilerplate solution means either a template you can use to start with or a CLI tool to generate your start project.

Using boilerplate solutions

Boilerplate solutions make it easy to set up a project with a solid architecture. This can be very helpful, but you should be aware of the trade-offs that come with these boilerplate solutions. Additionally, you should know exactly what you want because there are completely different solutions out there.

First, a boilerplate solution in this context is everything that creates code for you to start without having to configure everything on your own. This can be anything, from a simple template that has built-in TypeScript support but nothing else to a complete CLI solution that brings you solutions for navigation, state management, fonts, animations, connection, and more such as the Ignite CLI by Infinite Red.

Because there is such a wide range of what a boilerplate solution consists of, it’s hard to make general assumptions about them. Nevertheless, what can be said is that the more that is packed into the boilerplate solution, the bigger the risk that anything inside is broken. Therefore, in this section, you will learn about the most common ones, every single solution with advantages, trade-offs, and how to use them.

Using the React Native TypeScript template

React Native comes with an integrated template engine. When you are using the React Native CLI to set up your project, you can work with a template flag. This is how you can use the React Native TypeScript template:

npx react-native init App

    --template react-native-template-typescript

This template does not come with any solution for navigation, state management, or anything else. It is the plain React Native Starter template, but with support for TypeScript. I like it very much because it is very simple, has nearly no dependencies, and lets you decide on what you need, while it does all the TypeScript compiler configuration for you.

Advantages of this include the following:

  • TypeScript support
  • No unwanted dependencies
  • Easy to maintain

Trade-offs include the following:

  • None

While the React Native TypeScript template is a no-brainer to use when starting a new project, the following boilerplate solutions are not that easy to decide on. This is because they come with more libraries attached.

Using React Native Boilerplate by thecodingmachine

This boilerplate also uses the built-in React Native template engine to work. But compared to the React Native TypeScript template, it already makes decisions on many things for you. It comes with Redux, Redux Persist, and the redux toolkit for state management, Axios for API calls, React Navigation, and Flipper integration. Additionally, it creates a good directory structure for your project. You can create a project based on this template with the following call:

npx react-native init MyApp

    --template @thecodingmachine/react-native-boilerplate

Because this template comes with a lot of predefined libraries, you should take a look at whether it is actively maintained and has been updated recently. Otherwise, you could start with very old versions of all the libraries that would need a potentially time-consuming update very soon.

Advantages of this include the following:

  • TypeScript support
  • Good libraries
  • Good project structure

Trade-offs of this include the following:

  • It uses Redux for State Management, so you might have to stick to that
  • At the time of writing, it was already three versions behind the most recent React Native release, so you will miss the most recent features and bug fixes

For more information on this boilerplate, please visit the official documentation at https://thecodingmachine.github.io/react-native-boilerplate/.

While these are good solutions, you should have a look to see whether they really fit your project. The next template comes with a slightly different configuration.

Using React Native Starter Kit by mcnamee

This boilerplate does not use any template engine or CLI. It is just a GitHub repository that you can download or clone and start with. Additionally, it comes with a useful structure and brings a lot of libraries.

It uses Redux and Rematch for state management, React Native Router Flux for navigation, and it also comes with Native Base as the UI library and Fastlane for deployment. Essentially, it brings you all you need to get your first result shipped in hours.

But again, please have a look at how well-maintained the template is. At the time of writing, the last release of React Native Router Flux was more than a year ago, which means one core library of the template is essentially unusable.

Advantages of this include the following:

  • Good project structure
  • Adds everything to get you going

Trade-offs of this include the following:

  • It uses Redux for State Management, so you might have to stick to that
  • It uses Native Base as UI Toolkit, so you might have to stick to that
  • It has an outdated navigation library, so you will have problems with the most recent versions of React Native

You can find more information about this template from the official GitHub page at https://github.com/mcnamee/react-native-starter-kit.

After looking at two boilerplate templates, we’ll have a look at two really extensive CLI tools to set up your project.

Working with Ignite CLI

Ignite is a boilerplate solution developed and maintained by Infinite Red, an awesome React Native company, doing awesome open source work. It is much more than a simple template. It is a complete CLI, replacing the built-in React Native init command.

With the following command, you can create a new app:

npx ignite-cli new YourAppName

This creates an application with a good folder structure, React Navigation for navigation, MobX-State-Tree for state management, apisauce for API calls, and, of course, TypeScript support. In addition to that, your project automatically supports Flipper and Reactotron for debugging, Detox for end-to-end tests, and Expo, including Expo web.

On top of all that, Ignite CLI comes with a feature called generators. With these generators, you can generate your models, components, screens, and navigators via the Ignite CLI. This means you can customize your project to your needs, without having to write these files from scratch. If you want to create a new component, you can use the following command:

npx ignite-cli generate component MyNewComponent

This command creates a component based on a template stored in the ignite/templates folder, which was created with your project.

Tip

When working with the Ignite generators, you can edit the templates that are used to generate your files. Just edit the templates in ignite/templates, and the generated files will include your changes. This means you can adapt the templates to your needs and standards, and then use the generators to ensure that everyone sticks to those standards.

While this setup is great for professional projects, it comes with a lot of library decisions built in. In particular, MobX-State-Tree for State Management is one you might want to have a look at. It is a great solution for state management, but it isn’t as popular as Redux or React Context, which means the community support is quite poor.

Advantages of this include the following:

  • Good project structure
  • Good debugging integration
  • Integration for Detox end-to-end testing
  • Localization integration
  • Generators

Trade-offs of this include the following:

  • It uses MobX-State-Tree for State Management, which isn’t as popular as Redux or React Context.
  • It has Expo integration out of the box. This will grow your app bundle size and adds another dependency.
  • It adds a lot of overhead for smaller projects

For more information on Ignite, please visit the GitHub page at https://github.com/infinitered/ignite.

Now you know different boilerplate solutions along with their advantages and trade-offs. Even if you don’t use a boilerplate solution for creating your projects, I would recommend having a look at the structure they create. This kind of structure is something you can build on.

After looking at these boilerplate solutions, next, we’ll focus on the UI part. There are also a lot of useful open source solutions out there, which will make your life a lot easier.

Finding and using high-quality UI libraries

UI libraries provide a predefined UI for the most common use cases. There are a lot of different UI libraries you can use for your project. But some are better than others. This section not only names the most popular ones, but it also gives you an idea of what you must look for when doing your own research.

A good UI library should meet the following criteria:

  • Well maintained: As with all libraries, it has to be well maintained. This means there are multiple contributors, there is good code quality, and there are regular releases. This is important to ensure that future version upgrades of React Native are supported.
  • Component-based: A React Native UI library should provide a set of components, which you can use out of the box.
  • Theming: The library should include theming options and be easily adaptable to your colors, fonts, paddings, and margins.
  • Type declarations: A good UI library should have type declarations for components and themes.

There are a lot of different UI libraries out there. I will introduce you to two of them in the following subsection, but since they don’t have to be the best fit for your project, please do your own research based on the criteria mentioned here before using either of them.

Working with React Native Paper

React Native Paper is a UI library based on Material Design. It is created and maintained by Callstack, a React Native company that is also working a lot on the React Native core, so these folks know what they are doing. This means the library sets a very high standard regarding code quality.

React Native Paper meets all the criteria defined in the previous subsection. The following features are included in React Native Paper:

  • Excellent theming support: Paper comes with integrated theming. You can easily change and extend the default themes and use them all over your app.
  • Type declarations: All of the components and themes come with type declarations.
  • Icons: Paper uses react-native-vector-icons and MaterialCommunityIcons to provide you with icons.
  • Over 30 pre-built components: All components are highly customizable and easy to use.
  • Excellent React Navigation integration: Paper integrates very well in the React Navigation library. This means you can use components such as Appbar as a custom navigation bar in React Navigation.

While React Native Paper is possibly the best UI library out there from a technical point of view, you must keep in mind that it is completely based on Google’s Material Design. This means you might not want to use it on iOS, since it makes your app look different than the iOS standards.

For more information about React Native Paper, its installation, and its usage, please visit the official documentation at https://callstack.github.io/react-native-paper/.

Another high-quality UI library is NativeBase. In the next subsection, you will learn about this library.

Working with NativeBase

NativeBase is a UI library that works for React Native alongside plain React. This means it not only works within your iOS and Android app, but it also works on your web app if you have one. For products with Android, iOS, and web support, this can be very useful because you can primarily use the same code base for all platforms.

Additionally, NativeBase meets all of the criteria defined in the first subsection of this section. The following features are included in NativeBase:

  • Excellent theming support: NativeBase also has very good theming support. Essentially, it works quite similarly to React Native Paper. You can easily change and extend the default themes and use them all over your app. It also supports light and dark modes out of the box.
  • Type declarations: All components and themes come with type declarations. You also have excellent documentation on how to extend these types when it comes to customizing themes or components.
  • Icons: NativeBase comes with its own icons, which are based on react-native-vector-icons for plain React Native projects or @expo/vector-icon for Expo projects.
  • Over 30 pre-built components: All components are highly customizable and easy to use.
  • Responsive support: NativeBase has excellent responsive design support. This means you can adapt your views to different screen sizes with just a few additional properties on your components.
  • Accessibility: Based on React Native ARIA, NativeBase provides accessibility support for all components. This means you can easily provide support for screen readers, ensure a good contrast ratio, and enable keyboard interactions for your app.

Additionally, NativeBase comes with a Figma file, which makes it an ideal starting point for creating your own design system with a design expert. All in all, it is a very good solution for creating a beautiful UI in record time.

For more information on NativeBase, please visit the official documentation at https://docs.nativebase.io/.

As already mentioned, there are a lot more open source UI libraries out there. Please check this list for the most popular ones:

  • React Native UI Kitten
  • React Native Elements
  • Material Kit Pro React Native by creative-tim
  • Nachos UI Kit for React Native

These UI libraries can save you a lot of time. But as you want to create an individual app experience for your users, you should only use them as a starting point. Fortunately, most of them are adaptive enough that you can use them to create your own design while using the battle-proven structure of the library.

As your projects grow, I would recommend extending the library of your choice with your own components. If you like and think you have something that can be interesting for others too, you can even give something back to the community by creating pull requests and extending the official library.

After looking at the UI libraries, in the next subsection, you’ll get to know another useful tool. This is especially useful when working on large applications, where UI components are shared between different repositories and where some developers only work on the UI components. It is called Storybook.

Using Storybook for React Native

Storybook is very popular in the plain React world. It is a tool that renders all your components in predefined states, so you can have a look at them without having to start your real app and navigate to the location where they are used.

With Storybook, you write stories, which are then packed into a storybook. Each of these stories contains a component. It also defines the location within the storybook. The following code example shows what a story can look like:

import {PrimaryButton} from '@components/PrimaryButton;
export default {
  title: 'components/PrimaryButton,
      component: PrimaryButton,
};
export const Standard = args => (
  <PrimaryButton {...args} />
);
Standard.args = {
  text: 'Primary Button',
      size: 'large',
          color: 'orange',
};
export const Alert = args => (
  <PrimaryButton {...args} />
);
Alert.args = {
  text: 'Alert Button',
      size: 'large',
          color: 'red',
};

In the first line, the PrimaryButton component is imported. The following default export defines the location in the storybook and which component the story is related to. The Standard const and the Alert const are different states, and the PrimaryButton component will be rendered and shown in the storybook. The corresponding args define this state:

Figure 9.1 – Storybook running in a browser

Figure 9.1 – Storybook running in a browser

Storybook on React Native either works on the iOS or Android simulator, a real device, or you can use React Native Web to create a web version of your components and render them into any browser. This is shown in Figure 9.1 and can be especially useful when working with designers.

Storybook makes it possible to develop your components isolated from the rest of the application. It not only shows you the component, but it also lets you change the properties within a storybook. So, you can see how your component will behave in your real application under different circumstances.

I wouldn’t use Storybook for small projects, but when your project and your team grow, Storybook can be a useful tool to increase your development speed on the UI part. This is especially the case when you have UI components that you share between different repositories. I would recommend this when you have multiple applications in your company that should all share the same look and feel.

In this case, a central repository for your components could be a good solution. With Storybook, this repository can be maintained by a developer and designer, without needing access to all your applications. You can read more about this in Chapter 10, Structuring Large-Scale, Multi-Platform Projects, in the Writing own libraries section.

For more information on Storybook, please visit the official documentation at https://storybook.js.org/.

Summary

In this chapter, you learned about useful tools for increasing code quality, catching the most common errors automatically, and speeding up the project setup along with the development process. You understood why type definitions are important and how to use ESLint and prettier to ensure your code meets certain criteria.

Additionally, you got to know the most popular React Native boilerplate solutions to start a project, and you learned what advantages and trade-offs each of these solutions have. At the end of the chapter, you learned about Storybook for React Native, how to use it, and in which scenarios it is a useful tool.

After learning about all these useful tools, it is time to dive deeper into large-scale projects. In the next chapter, you will learn how to set up and maintain a project structure, which will work for large-scale projects. Additionally, you will learn what options you have, to share code between different platforms, and which of these solutions works best in which scenario.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset