Best headless UI libraries in React Native
Tags: reactnative, ui, webdev
Published: 2023-10-04 17:11:14

**Written by [Hussain Arif](https://blog.logrocket.com/author/hussain-arif/)✏️**

In this article, we will learn what headless component libraries are and when to use them, as well as learn about popular options for headless UI libraries in the React Native ecosystem. 

Here’s what we’ll discuss today:

*   [What is a headless UI library, and what problems can it solve?](#headless-ui-library-problems-solve)
*   [Tamagui](#tamagui)
    *   [Pros and cons of Tamagui](#pros-cons-tamagui)
*   [NativeWind](#nativewind)
    *   [Pros and cons of NativeWind](#pros-cons-nativewind)
*   [Dripsy](#dripsy)
    *   [Pros and cons of Dripsy](#pros-cons-dripsy)
*   [Gluestack](#gluestack)
    *   [Pros and cons of Gluestack](#pros-cons-gluestack)
*   [Comparison table](#comparison-table)

You can find the source code repositories for the examples of [Tamagui](https://github.com/HussainArif12/react-native-tamagui), [NativeWind](https://github.com/HussainArif12/react-native-native-wind), [Dripsy](https://github.com/HussainArif12/react-native-dripsy), and [Gluestack](https://github.com/HussainArif12/gluestack-demo) on my GitHub.

## What is a headless UI library, and what problems can it solve? <a name="headless-ui-library-problems-solve">

As developers, we often build complex apps and websites for clients. This involves components that are complicated to build and very tricky to style. 

In many cases, building custom components from scratch is a demanding and time-consuming endeavor because we have to look after a plethora of requirements, which may include:

*   Making sure that the component works as intended across all platforms and browsers
*   Ensuring that it is performant and does not have any memory leaks
*   Moreover, confirm whether the dependencies of that custom element are up to date

As an example, let’s take this `ListBox` component: ![A ListBox component example](https://blog.logrocket.com/wp-content/uploads/2023/09/listbox-component-example.gif) As you can see, replicating this behavior in a custom React component is not easy at all. So how do we fix this problem? This is where headless component libraries come in. 

They are essentially a set of components that provide the logic, processing, and API, but rely on the developer for styling. In simpler words, these libraries handle all the heavy lifting and all we have to do is to make them look good. 

Now that we have learned about the fundamentals of this concept, let’s now explore some popular component libraries for React Native.

## Tamagui <a name="tamagui">

[Tamagui](https://blog.logrocket.com/tamagui-react-native-create-faster-design-systems/) is a library that provides universally styled components for both React and React Native platforms. Its biggest advantage is that since it supports React and Native, the styling code is unified between both web and mobile platforms. Furthermore, the team also maintains that [performance is better than other competing libraries](https://tamagui.dev/docs/intro/benchmarks). 

To integrate Tamagui into your Expo app, follow these [instructions](https://tamagui.dev/docs/guides/expo). When that’s done, write the following code in your `App.js` file:

```javascript
import { useFonts } from "expo-font";
import { Button, Paragraph, TamaguiProvider, Theme, YStack } from "tamagui";
import config from "./tamagui.config";

export default function App() {
  const [loaded] = useFonts({
    Inter: require("@tamagui/font-inter/otf/Inter-Medium.otf"),
    InterBold: require("@tamagui/font-inter/otf/Inter-Bold.otf"),
  });
  //Render the UI as soon as the resources are loaded
  if (!loaded) {
    return null;
  }

  return (
    <TamaguiProvider config={config}>
      {/*Render a View with dark theme*/}
      <Theme name={"dark"}>
        <YStack f={1} jc="center" ai="center" backgroundColor={"pink"}>
          {/*Render some text onto the screen*/}
          <Paragraph color="black" jc="center" fontSize={50} lineHeight={80}>
            Black
          </Paragraph>
        </YStack>
      </Theme>
      {/*Render another view with light theme*/}
      <Theme name="light">
        <YStack f={1} ai="center" jc="center" backgroundColor="black">
          <Paragraph color="pink" jc="center" fontSize={50} lineHeight={80}>
            Pink
          </Paragraph>
        </YStack>
      </Theme>
      {/*Render a third View with dark theme and display a button*/}
      <Theme name="dark">
        <Button color={"$pink10Dark"}> I am a dark button</Button>
      </Theme>
    </TamaguiProvider>
  );
}
```

Let’s test it out! To run this code, run this Bash command:

```bash
npm run start-android
```

![Tamagui rendering example](https://blog.logrocket.com/wp-content/uploads/2023/09/tamagui-rendering-example.png)

### Pros and cons of Tamagui <a name="pros-cons-tamagui">

Here are a few factors that make it a great library:

*   Supports Expo CLI, which gives developers more choice when it comes to building React Native apps
*   The library uses a concept called [tokens](https://tamagui.dev/docs/core/tokens), which is a feature that offers detailed control over the styling and theming of components
*   It’s faster than other component libraries
*   As shown in the code above, Tamagui allows developers to have multiple theming options on the same screen

However, there are some things that I didn’t like about Tamagui:

*   The [setup process for Expo apps](https://tamagui.dev/docs/guides/expo) is tedious
*   Documentation is not easy to follow. As a result, this might deter new developers from using the Tamagui technology
*   The library does not follow Tailwind’s styling conventions, which prevents us from using class names to style our React components

## NativeWind <a name="nativewind">

[NativeWind](https://www.nativewind.dev/) is another tool that allows developers to share styling code between React and React Native platforms. However, unlike Tamagui, its key feature is that it lets users use Tailwind’s scripting language to decorate UI elements. 

First, to integrate NativeWind in your Expo app, [follow these steps](https://www.nativewind.dev/quick-starts/expo). Next, in your `tailwind.config.app`, add the following lines of code:

```javascript
module.exports = {
  content: [
    "./app/**/*.{js,jsx,ts,tsx}",
    "/*.{js,jsx,ts,tsx}",
    "./App.{js,jsx,ts,tsx}", //ensures that App.js is styled as well
  ],
//further code..
```

Let’s now see it in action! To do so, replace all the code in `App.js` with the following:

```javascript
import { StatusBar } from "expo-status-bar";
import { Text, View } from "react-native";
import "./global.css";
export default function App() {
  return (
    //apply Tailwind styling to our React Native elements..
    <View className="flex-1 items-center justify-center bg-blue-400">
      <Text className="px-8 text-lg text-rose-800">
        This style is being applied with NativeWind
      </Text>
      <StatusBar style="auto" />
    </View>
  );
}
```

To run the code, execute this Bash command:

```bash
npx expo start -c #clear the cache and then run the app
```

![NativeWind rendering example](https://blog.logrocket.com/wp-content/uploads/2023/09/nativewind-rendering-example.png)

### Pros and cons of NativeWind <a name="pros-cons-nativewind">

Here are a few key features that help NativeWind stand out:

*   Uses Tailwind’s styling convention, which means that designing components is relatively easier than Tamagui
*   Small runtime, which brings great performance to the table
*   Easy to set up
*   Clear documentation
*   Supports Expo

However, there was one thing that made it unappealing:

*   At the time of writing of this article, [the library currently relies on an older version of TailwindCSS](https://github.com/marklawlor/nativewind/issues/498)

## Dripsy <a name="dripsy">

Dripsy is another React Native library that, like Tamagui and NativeWind, aids users in unifying styling code between web and mobile. Moreover, compared to its counterparts, Dripsy has a remarkably simple setup process. 

To use Dripsy in your app, install it like so:

```bash
npm install dripsy
```

That’s it! To use this library, write the following code in your `App.js` file:

```javascript
import { StatusBar } from "expo-status-bar";
import { View, Text } from "dripsy";
import { DripsyProvider } from "dripsy";

export default function App() {
  return (
    <DripsyProvider>
      <View
        //use the 'sx' prop to style our component
        sx={{
          height: "100%",
          backgroundColor: "green",
        }}
      >
        <Text sx={{ marginY: 100, color: "rgb(255,255,255)", fontSize: 30 }}>
          This was styled with Dripsy
        </Text>
        <StatusBar style="auto" />
      </View>
    </DripsyProvider>
  );
}
```

Let’s now see it in action! Run this piece of code in your terminal:

```bash
npx expo start -c
```

![Dripsy rendering example](https://blog.logrocket.com/wp-content/uploads/2023/09/dripsy-rendering-example.png)

### Pros and cons of Dripsy <a name="pros-cons-dripsy">

Here are some of the reasons why Dripsy might be suitable for you:

*   Uses the `sx` prop for more control over UI styling. Furthermore, this prop is also [memoized](https://blog.logrocket.com/when-not-to-use-usememo-react-hook/) out of the box, thus promising a responsive app
*   Lets developers use [custom fonts](https://www.dripsy.xyz/fonts). As discussed before, this allows for more customization options
*   [Can override themes](https://www.dripsy.xyz/usage/theming/color-modes)
*   The setup process is a walk in the park as compared to other alternative libraries

But one thing you want to look out for is:

*   This library is not frequently updated. As of this article, the latest update was four months ago

## Gluestack <a name="gluestack">

Just like the other libraries mentioned in this article, [Gluestack](https://ui.gluestack.io/docs/overview/introduction) is another unstyled component library. Originally a part of [NativeBase](https://nativebase.io/), the developer team created this library to [prevent bloat and enhance maintainability](https://nativebase.io/blogs/road-ahead-with-gluestack-ui) of the project. 

To install Gluestack in an Expo project, run this Bash command:

```bash
npm i @gluestack-ui/themed @gluestack-style/react react-native-svg@13.4.0
```

This block of code demonstrates sample usage of the Gluestack technology:

```javascript
import { GluestackUIProvider, Text, Box, config } from "@gluestack-ui/themed";

export default function App() {
  return (
    //use the default config
    <GluestackUIProvider config={config.theme}>
      {/*Create first Box element with black background color*/}
      <Box
        width="100%"
        height="50%"
        justifyContent="center"
        alignItems="center"
        bgColor="black"
      >
        <Text color="white">This text was styled using Gluestack</Text>
      </Box>
      {/*Create second Box element with pink background color*/}
      <Box
        width="100%"
        height={"50%"}
        justifyContent="center"
        alignItems="center"
        bgColor="pink"
      >
        <Text color="blue">This second block of text was styled as well</Text>
      </Box>
    </GluestackUIProvider>
  );
}
```

This will be the result: ![Gluestack rendering example](https://blog.logrocket.com/wp-content/uploads/2023/09/gluestack-rendering-example.png)

### Pros and cons of Gluestack <a name="pros-cons-gluestack">

Here are a few factors that make it a decent choice for your project:

*   Provides animations out of the box: This means that users don’t need to manually implement animations in their app
*   Extensive theming: [Gluestack’s theming config](https://ui.gluestack.io/docs/theme/overview) resembles Tamagui’s, which means developers need to use tokens to customize and style their components. This results in a shallower learning curve
*   Extensive list of components, which ensures that users can easily pick and choose between Native components depending on their needs

However, there are some things that you might want to consider before integrating Gluestack in your app:

*   At the time of this article, the library relies on an older version of `react-native-svg`. This may break the app due to dependency conflicts:

![Gluestack has dependency conflicts with the newest versions of react-native-svg](https://blog.logrocket.com/wp-content/uploads/2023/09/dependency-conflicts-gluestack.png)

## Comparison table <a name="comparison-table">

Here is a table that summarizes all the key features of the libraries discussed earlier:

<table>

<thead>

<tr>

<th>Aspect</th>

<th>Tamagui</th>

<th>NativeWind</th>

<th>Dripsy</th>

<th>Gluestack</th>

</tr>

</thead>

<tbody>

<tr>

<td>Styling convention</td>

<td>Custom tokens</td>

<td>TailwindCSS</td>

<td>`sx` prop for styling</td>

<td>Custom tokens</td>

</tr>

<tr>

<td>Performance</td>

<td>Faster than others</td>

<td>Small runtime, good performance</td>

<td>Responsive, memoized `sx` prop</td>

<td>Substantially faster than NativeBase. Slower than other alternatives, but still competitive</td>

</tr>

<tr>

<td>Setup process</td>

<td>Tedious for Expo apps, easy for other integrations</td>

<td>Easy to setup for all integrations</td>

<td>Straightforward setup for all integrations</td>

<td>Straightforward setup for all integrations</td>

</tr>

<tr>

<td>Documentation</td>

<td>Not easy to follow (but [LogRocket has a good guide](https://blog.logrocket.com/tamagui-react-native-create-faster-design-systems/))</td>

<td>Clear documentation</td>

<td>Detailed and easy to follow</td>

<td>Details and easy to follow</td>

</tr>

<tr>

<td>Theming options</td>

<td>Multiple theming on one screen. Can override themes</td>

<td>Same as TailwindCSS</td>

<td>Can override themes</td>

<td>Can override themes</td>

</tr>

<tr>

<td>Custom fonts</td>

<td>No</td>

<td>No</td>

<td>Yes</td>

<td>No</td>

</tr>

<tr>

<td>Follows Tailwind’s convention</td>

<td>No</td>

<td>Yes</td>

<td>No</td>

<td>No</td>

</tr>

<tr>

<td>Update frequency</td>

<td>Frequent updates</td>

<td>Regular updates</td>

<td>Infrequent updates</td>

<td>Frequent updates</td>

</tr>

<tr>

<td>Integrations</td>

<td>React Native, Next.js, React</td>

<td>React Native, Next.js, React</td>

<td>React Native, Next.js</td>

<td>React Native, React, Next.js</td>

</tr>

</tbody>

</table>

## Conclusion

Here are the source code repositories for the examples of [Tamagui](https://github.com/HussainArif12/react-native-tamagui), [NativeWind](https://github.com/HussainArif12/react-native-native-wind), [Dripsy](https://github.com/HussainArif12/react-native-dripsy), and [Gluestack](https://github.com/HussainArif12/gluestack-demo). 

In this article, we briefly discussed the importance of headless component libraries. Furthermore, we also compared some of the most popular headless component technologies for React Native. 

In my personal projects, I use NativeWind because it follows Tailwind’s styling language, thus making it effortless to decorate and design UI components. Thank you so much for reading!

---

##[LogRocket](https://lp.logrocket.com/blg/react-native-signup): Instantly recreate issues in your React Native apps.

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2021/10/react-native-plug_v2-2.png)](https://lp.logrocket.com/blg/react-native-signup)

[LogRocket](https://lp.logrocket.com/blg/react-native-signup) is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.

LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.

Start proactively monitoring your React Native apps — [try LogRocket for free](https://lp.logrocket.com/blg/react-native-signup).