How to create React Native component library
Tags: reactnative, mobile, javascript
Published: 2024-02-04 15:18:38

## Introduction

Sharing and reusing code across projects can significantly boost productivity and maintainability of software projects. One of the most efficient ways to share UI components and logic for _React Native_ is by creating a component library. This article will guide you through the process of creating a _React Native_ component library using [create-react-native-library](https://callstack.github.io/react-native-builder-bob/create), a tool designed to streamline the creation and management of _React Native_ libraries.

## Why Create a React Native Library?

Before diving into the how, let's explore the why. Creating a React Native library allows you to:

- Reuse code across multiple projects, reducing duplication and effort.
- Share components within your team or with the wider community.
- Encapsulate and abstract functionality, making your main project cleaner and more focused.

## Setting Up the Environment

Ensure [Node.js](https://nodejs.org/en/download) is installed on your machine and the React Native CLI environment was set up following the [official React Native setup guide](https://reactnative.dev/docs/environment-setup).

### Step 1: Creating Your Library

`create-react-native-library` provides a straightforward command-line interface to scaffold a library. It containts several CLIs to streamline the process. To create a new library, open a terminal and run:

`npx create-react-native-library@latest awesome-library`

Replace _react-native-awesome-component_ with the name of your library. The tool will generate a new directory with the given name, including a basic project structure. Make sure to select **JavaScript library** in the upcoming dialogue.

Next, go into the folder via `cd react-native-awesome-component` and run `npm i`. It could be that you have to run it with the `--legacy-peer-deps` option, if you get an error. There seems to be a dependency broken at the moment.

### Step 2: Exploring the Generated Structure

Navigate into the library's directory. There are several important files and folders:

- _src/_ - This is where the library's source code for _React Native_ components will reside.
- _example/_ - A generated _React Native_ app to test the library during development.
- _package.json_ - Defines the library's dependencies and scripts.

### Step 3: Developing a Component

With the library scafolded, it's time to start developing a component. Edit the files within the _src/_ directory to implement components. For simplicity, we will use the `AppButton`, created in another [tutorial](https://dev.to/9bytes/crafting-a-custom-button-component-in-react-native-2inj), to use directly in _index.tsx_ file. This is just for the sake of this tutorial. In a real world library, every component should have it's own file and just be imported into the _index.tsx_:

```tsx
import React from "react";
import {
  Pressable,
  StyleSheet,
  Text,
  type GestureResponderEvent,
  type ViewStyle,
  type TextStyle,
} from "react-native";

interface Props {
  disabled?: boolean;
  color?: string;
  buttonStyles?: ViewStyle;
  textStyles?: TextStyle;
  accessibilityLabel?: string;
  onPress: (event: GestureResponderEvent) => void;
}

const AppButton: React.FC<Props> = (props) => {
  return (
    <Pressable
      style={({ pressed }) => [
        {
          backgroundColor: props.disabled
            ? "#ccc"
            : pressed
            ? "#aa0000"
            : props.color || "red",
        },
        styles.container,
        props.buttonStyles,
      ]}
      disabled={props.disabled}
      onPress={props.onPress}
      accessible
      accessibilityLabel={props.accessibilityLabel || "A Button"}
    >
      <Text style={[styles.text, props.textStyles]}>
        {props.children || "Press Me"}
      </Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 8,
    alignItems: "center",
    borderRadius: 8,
  },
  text: { color: "white" },
});

export default AppButton;
```

### Step 4: Testing the Component

Leverage the generated example app to test the component:

1. Navigate to the _example/_ directory via `cd example`.
2. Install dependencies with `npm install` or `yarn`.
3. Run the app on iOS or Android using `npx react-native start`.

Make sure to import and use the `AppButton` component in the example app to see it in action:

```tsx
import * as React from "react";

import { StyleSheet, View, Text } from "react-native";
import AppButton from "react-native-awesome-library";

export default function App() {
  const [result, setResult] = React.useState<number>(0);

  return (
    <View style={styles.container}>
      <AppButton onPress={() => setResult((i) => ++i)}>Multiply</AppButton>
      <Text>Result: {result}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  box: {
    width: 60,
    height: 60,
    marginVertical: 20,
  },
});
```

### Step 5: Hosting the Library

There are several options to host the library:

#### npm (Node Package Manager)

- Public Hosting: [npm](https://www.npmjs.com/) is the default package manager for _Node.js_ and is the largest ecosystem of open source libraries. The library can be publish to npm to make it publicly available.
- Private Hosting: _npm_ also offers private packages as part of its paid plans. This is useful for companies or teams that want to share code internally without exposing it to the public.

#### GitHub Packages

- _GitHub_ Integration: [GitHub Packages](https://github.com/features/packages) allows you to host your npm packages directly on _GitHub_, making it easy to share your packages with others, either publicly or privately within an organization. It integrates closely with _GitHub_'s permissions and workflow, making it a convenient option for teams already using GitHub for source control.
- Support for Multiple Registries: Besides _npm_, _GitHub Packages_ also supports hosting for other package types, such as Docker containers, Maven packages, NuGet packages, and more.

#### Verdaccio

- Private Proxy Registry: [Verdaccio](https://verdaccio.org/) is a lightweight, open-source private _npm_ proxy registry. It allows to set up a local _npm_ registry with minimal setup, perfect for teams needing a private registry without the cost of _npm_'s private packages.
- Caching and Local Publishing: _Verdaccio_ caches downloaded public packages and allows to publish private packages.

#### Bit

- Component Collaboration: [Bit](https://bit.dev/) is a tool designed for sharing and collaborating on individual components across projects.
- Versioning and Isolation: _Bit_ handles component versioning, dependency isolation, and updates, making it easier to maintain and update components across multiple projects.

### Step 6: Publishing the Library

After selecting where to host the library, it can be published.

1. Ensure that package.json is properly filled out with the library's information and `version`.
2. Depending where the library is hosted, the `publishConfig` has to be updated with the correct link, for example:

```json
"publishConfig": {
    "registry": "https://registry.npmjs.org/"
  },
```

3. Run `npm run prepare` to build the components and create the exports.
4. Publish the library using `npm publish`.

## Conclusion

Creating a _React Native_ component library is a powerful way to streamline the development process and foster code reuse. Using `create-react-native-library` simplifies the process of library creation. By following the steps outlined in this guide, it is easy to develop a reusable component library that can enhance any _React Native_ project.