React Native Best Practices

Part 1: Maximizing financial benefits from the code.

Sebastian Barcenas
Bits and Pieces

--

Hello guys, and nice to see you here, my name is Sebastian, a Sytems Engineer with a lot of experience building incredible apps using React, React Native & Node.js.

Today, I am going to share the most valuable lessons I have learned during my time with React Native. I will strive to make this article as valuable as possible by providing detailed explanations for each practice we cover.

I hope you are ready to learn much about React Native before you start building the incredible project you have planned.

React Native Best Practices

Use TypeScript with your React Native app.

Types are important because well-typed code has several benefits, from improving readability to speeding up development and preventing bugs in the process of your React Native app.

Typing your code ensures that the next time a developer reads it, they can easily understand what’s happening.

function getFinalValue(coolObject) {
return coolObject.value + 1900;
}

I know, the function name is not okay, and also the arguments may have a more descriptive name, but with educative purposes let’s say this is the function a Junior developer in your company wrote in response to a common operation in the code.

Someday a new requirement comes up, and you have to extend a bit the functionality. What a big trouble!

Now you have to dig in the whole code for clues about what exactly this function is getting as parameters. Believe me, it’s even more complicated when the data comes from another side like an API, and even more, if this API has no good documentation.

Here’s when TypeScript comes to make sure we write more scalable code.

interface CoolObjectInterface {
value: number;
name: string;
taxPercentage: number;
}

function getFinalValue(coolObject: CoolObjectInterface) {
const { value: price, taxPercentage } = coolObject;
const taxValue = price * taxPercentage;
return price + taxValue;
}

Here we go! Same function, but now you and your editor are aware of the object properties and their types in code, which made it easier to extend the functionality.

It’s just an example of several advantages TypeScript can bring to your projects, in terms of development efficiency, but if you are still interested into know more advantages of using Typescript in your React Native Project, you can check it in the article.

💡 Also, consider adopting a component-driven approach for developing bigger React Native apps using tools like Bit. With Bit you can version, test, publish and share reusable components across multiple projects.

Learn more:

Prioritize the use of Functional Components over the Class Components.

I know it sounds obvious if you have some experience with React, but it’s essential if you’re a new developer reading this article to know functional components have everything you need to build great apps, with less complexity and more performance at a time to create React Native apps.

And I know, “There are some cases where you can’t yet choose for functional components, like error boundaries”.

Just keep your code as functional as possible, because it has several advantages:

  1. Increases code readability
  2. Increases the performance of the components
  3. Are easy to test
  4. Pay as you go — What? Is it not free to develop in react native? (I mean performance price 👐)

No worries, I'll not give you a checklist without no any explanation let’s do a quick explanation about the main difference between functional and class components and just maybe those points will make a lot of sense.

// Functional Component
function Welcome(props) {
return <Text>Hello, {props.name}</Text>;
}
// Class component
class Welcome extends React.Component {
render() {
return <Text>Hello, {this.props.name}</Text>;
}
}

At first glance we can say, yes looks a bit more complex to create a functional component but it’s not too bad.

But let’s dive a bit more into what’s happening here,

  1. A React Functional Component is a simple JavaScript function that returns JSX.
  2. Class Components are ES6-based classes
  3. Class Components must extend from React.Component to work
  4. Class Components must use a render method to return the JSX result
  5. Class components have state management logic as a fundamental part of them
  6. Class components have Lifecycle events as a fundamental part of them
  7. Hooks are available since React 16.8 and allow us to add states and lifecycle events to our functional components on demand.

And now does it make sense for you to use Functional components?

If you want to get further information about components in React, please visit https://reactjs.org/docs/components-and-props.html.

Dumb components are great

I know, if you maybe don’t know what dumb components are, you can check my article here. But I evet will try to explain it here.

In short, dumb components are the ones that are rendering styles but not handling the data. They just are getting data from props and displaying it for you. Generally, dumb components are used in the container/components pattern, where the container component fetches the data and send it as props to the dumb or presentational component.

Resource from: https://www.patterns.dev/posts/presentational-container-pattern/

It’s a really good pattern to have in your project because your components will be more readable, easier to edit, and most importantly, will be reusable and easy to share between different screens, saving you hundreds of hours at a time to code new screens with similar components inside.

Create a good Theme

Communication between designers and developers is very important because following good patterns and standardization could make the process smoother, from reusing spaces and colors to using well-defined breakpoints are incredible benefits to using a Theme inside your application.

Styled Components is a good example of a great tool, that allows us to easily create a theme, and share those values across your application. With a friendly syntax similar to the one we use for React Applications.

But even you can create this kind of theme manually with a wrapper function to React Native StyleSheet functionality.

type Style<K extends string> = {
[key in K]: ViewStyle | ImageStyle | TextStyle;
};

type ThemedStyle<K extends string, T extends object = object> = (
theme: Theme,
props?: T,
) => Style<K>;

export function createUseStyle<K extends string, P extends object>(
style: Style<K> | StyleSheet.NamedStyles<Style<K>> | ThemedStyle<K, P>,
) {

function useStyle(props?: P) {
const { theme } = useTheme();

return typeof style === 'function'
? StyleSheet.create(style(theme, props))
: StyleSheet.create(style);
}

return useStyle;
}

Wait wait, what’s happening here and how could this function help me to define a theme in React Native without libraries?

In simple words, this function is receiving your style function and through a hook that exposes a context, passes the theme as an argument, to your function, then you will be able to access the theme in your code style function.

Note: “”

// Use this function to create your styles instead of StyleSheet.create({...})

const useStyle = createUseStyle(
(
theme,
props
) => ({
textElement: {
fontSize: theme.fontSizes.s,
},
}),
);

Now you can call your styles in your component using the hook that this function returns.

// Functional Component
function Welcome(props) {
const {name} = props;
...
// You could send useful props to your styles
const styles = useStyle({isDark});
return <Text style={styles.textElement}>Hello, {name}</Text>;
}

💡 Note: If your projects are bigger, consider building a proper design system that is composable and scalable, using Bit’s open-sourced ThemeProvider that lets you quickly build a full theming solution with the Context API and design tokens.

To learn more about theming components with React:

Find out more:

Import your dependencies in order

Sometimes we can get a lot of imports in a single file and can be annoying trying to identify where a specific import is, it could cost time and headaches to the rest of the team.

But also sometimes the import order can affect the behavior of some of your components, and it can bring bugs really hard to identify.

  1. External imports — react
  2. Internal imports, like relative paths — ../button
  3. In folder imports like ./styles.ts
  4. The imports may be sorted alphabetically in every group
  5. Every group must be divided by white space — Please don’t add comments to every group in every file in your project, it could be redundant and also a waste of bytes in your file 😹.
import React from 'react';
import { TouchableOpacity, View } from 'react-native';

// A redudant comment trying to demostrate I comment my code
import { Button, Card } from '../components'
import { MainLayout } from '../layouts'

import { StyledCard } from './styles.ts'

I know it may sound like more work and time to build your React Native Components, but here’s some good news: we can automate this process using linting tools like Eslint and formatting tools like Prettier.

No connection first apps is a rule

Please make sure you have a well-defined path, for not connected users, to make sure, the friction in your application is not a problem for users with connection issues.

Storing meaningful information in the AsyncStorage non-sensible data, makes your app works even without a connection.

Note: Sometimes your applications functionality depends on users’ sensitive data, and it’s not a good practice to save this information in the Async Storage. In that case, you can follow the security section in the React Native docs, to choose the right library to store this information.

Configure global paths

Here you go, it's very important to have aliases for our main folders in the app, to avoid using confusing relative paths.

import { Component } from '../../../components/shared/something' // Wrong

But how can we solve it? — In order to fix this issue, we can use babel-plugin-module-resolver, which allows us to specify how a keyword will be treated in an import statement.

I won’t delve too deeply into the technical implementation in this article, but you can read more about it here (Writing article yet! 🧑‍🎓).

Conclusion

My biggest conclusion here is that a single article is not enough to cover all the lessons I learned during this time. That’s why I’ll turn this into a series of articles to guide you through React Native best practices.

The second and most important lesson here is how we can save tons of time by following best practices in React Native.

In Software Development Time is money, and adhering to best practices helps us maximize our financial resources while changing the world through technology.

I hope you enjoyed this section, see you in the next one.

Build Apps with reusable components, just like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--