How to use Chakra UI on native mobile
Tags: reactnative, react, css, ssr
Published: 2021-04-01 18:41:32

—— Update 2022-12-29

I currently recommend using the recently launched v1.0 of [Tamagui.dev](tamagui.dev) instead of NativeBase, due to [NativeBase’s performance issues](https://github.com/GeekyAnts/NativeBase/issues/4302). Tamagui has a Radix UI inspired component library (plus styling solution), with great look-and-feel. It does not have as many components as Chakra or NativeBase yet, but is expanding in an impressive pace. ([Nativewind.dev](nativewind.dev) is an alternative for the Tailwind inclined, but I’m not aware of any native compatible component library for Nativewind).

[Chakra UI will likely never come to native](https://github.com/chakra-ui/chakra-ui/issues/183) as the whole lib would have to be rewritten for React Native (+Web) support, and [Chakra team has no plans to do that as of 2022-04-08](https://twitter.com/chakra_ui/status/1512458794215022595).

--- Update 2021-10-16

The currently recommended way is to use [NativeBase](https://nativebase.io/) as base UI components, and then use only the theme of Chakra UI, to get Chakra's superior look-and-feel:

https://github.com/chakra-ui/chakra-ui/issues/183#issuecomment-915429383

Until Chakra UI comes to native. Which can take a while, since Chakra uses it's own CSS-in-JS (emotionjs), the whole library [will likely have to be rewritten](https://github.com/chakra-ui/chakra-ui/issues/183#issuecomment-559810732).

--- Update 2021-05-03 (one month later)

**Chakra UI has just announced they will be coming to Native "pretty soon"!**

https://twitter.com/chakra_ui/status/1388033321213612032?s=21

--- (original blog post below)

This post grew out of the discussion on [the React Native issue for Chakra UI](https://github.com/chakra-ui/chakra-ui/issues/183), plus my own research. I fear some of the brief points @steida made on the issue were lost to some, as they were to me, so I decided to write a bit more thoroughly on them.

First, a primer on [React Native Web](https://necolas.github.io/react-native-web/docs/) (RNW), for those unfamiliar. RNW is taking the high-level API of React Native, onto the Web. "Why not just use React?", you say. RNW is all about using specifically tailored _native cross-platform components_ (that primarily render onto a native Screen view) and also rendering them on the web (to the DOM). Which is possible because RN/RNW uses higher-level abstractions (`<View>` and `<Text>` instead of `<div>` and `<span>`, etc.). (RNW should have been called "React Platform", really.)

## You can't use Chakra UI with React Native or React Native Web, since they already have styling baked in.

Like @steida said, **React Native Web (RNW) has its own fully integrated styling solution, StyleSheet, which has its own API**. 
The StyleSheet solution comes from RN, naturally. But on web, with RNW, it needs some justification. Why not simply use any other stylesheet solution? In short: To have a uniform styling API across RN and RNW. But there are other benefits too, like working with a higher-level abstraction:

React Native Web abstracts away the complexities of CSS. **CSS allows 3 ways of styling, which make it complex** (unless you “own the whole stack”, like RN and RNW):
- statically (css file; cacheable and fast)
- dynamic runtime styling (props object or inline styles; flexible)
- escape hatch styling (hooking into DOM nodes outside of React; typically used for animations).

>“The React-DOM ecosystem doesn’t have a foundation upon which everything else is built. So, in RN if you install a RN package, then (pretty much) everything is using the same style library, using the same measurements etc. so it can interop at this quite broad level.” - [Nicolas Gallagher, RNW creator, at 29:00 in this 2018 podcast](https://podcasts.apple.com/no/podcast/react-podcast/id1341969432?l=nb&i=1000401004806)

The [StyleSheet](https://reactnative.dev/docs/stylesheet) solution that RN/RNW has is one of the fastest CSS-in-JS solutions, apparently, [according to Evan Bacon](https://www.reddit.com/r/reactnative/comments/khoxpm/should_i_go_with_reactnativeweb_or_standard_react/ggmlbk6?utm_source=share&utm_medium=web2x&context=3), Expo Web creator.

So React Native has its own fully integrated props based styling API. Thus, integrating Chakra UI with RN/RNW could be particularly challenging, because you risk losing that high level styling API which RN/RNW are all about. That's also why you don't want to use an extra CSS-in-JS library like styled-components or emotionjs on top of RNW, like @steida expressed. (I don't think people still attempt to do that because they dislike the RNW solution, or prefer string interpolation instead of RNW's StyleSheet. They are just confused, like I was, and think they need a styling solution with RN/RNW, when in reality it is already baked in.)

So you can't currently use Chakra UI out of the box with React Native.

Neither would you want to do it in RNW, because of RNW's high level API. RNW is not meant for using a component library made for web, such as Chakra UI, on native. To do that, while also getting the cross-platform benefits of RNW, then Chakra UI would have to be rewritten from the bottom-up with those higher-level abstractions in mind (`<View>` instead of `<div>` etc., and with [StyleSheet](https://reactnative.dev/docs/stylesheet) instead of [styled-system and emotion](https://chakra-ui.com/docs/comparison#the-runtime-trade-off-) under the hood). This is not likely to happen. [The issue](https://github.com/chakra-ui/chakra-ui/issues/183) has not had much progress since Oct 2019, and was closed in Apr 2020.

It's probably better to **use Chakra UI where it shines: on the web**. _Many websites and webapps don't need to be native_, after all. Going for RN or RNW for them would be pure overhead (even though [Expo Web](https://docs.expo.io/workflow/web/) has done great things to reduce that overhead..).

## Unless you want to circumvent the React Native Web API

> In the TypeScript implementation, I'm extracting most of the component logic into hooks so it can be consumed in React Native Web and React (Web). Perhaps, it might help. - [segundeadebayo, Chakra UI creator](https://github.com/chakra-ui/chakra-ui/issues/183#issuecomment-559813770)

But, as said, integrating Chakra UI with RNW wouldn't be particularly desirable, because you'd lose that high level API which RNW is all about. So it defeats the point of using RNW at all.

## And unless you want to make a mobile app that exposes a WebView and loads in a webpage with ChakraUI on it.

Though you could use RN to make a native wrapper/shell app that exposes a WebView in which you load your webapp that uses Chakra UI, of course.

But then you would have to [write your own bridge](https://m.signalvnoise.com/basecamp-3-for-ios-hybrid-architecture/) to *communicate between your native app and your webapp* (at least until Basecamp open sources their bridge for that, [Hotwire Strada](https://hotwire.dev/), later this year). You might be able to write the native app in React Native, and [communicate with the webapp through the WebView](https://stackoverflow.com/questions/53297300/how-to-communcation-between-web-inside-webview-back-to-react-native-apps), but this is hacky, and I'd rather rely on a [proper bridge of some sorts](https://medium.com/react-native-training/improving-communication-between-react-native-webviews-and-the-webpages-they-render-792c8f7db3e5).

NB: This type of bridge is not the same as [RN's own bridge](https://litslink.com/blog/new-react-native-architecture) which is between the RN app and the native platform.

[Capacitor](https://capacitorjs.com/), as an alternative to RN, is the only solution I know of that will easily give you a _single direct bridge_ between your webapp and the native platform (think '[Electron](https://www.electronjs.org/) for mobile'). Read more on Capacitor at the end of this post.


## Magnus UI vs. Dripsy - Chakra UI alternatives for RN/RNW

If you want to use RN/RNW and want to use a component library like Chakra UI, then you have two good alternatives, to my knowledge. Especially if you want to use NextJS to do Server-Side Rendering (SSR) of the webapp/PWA.

Here is a [comparison of Magnus UI vs Dripsy](https://dev.to/redbar0n/magnus-ui-vs-dripsy-chakra-ui-alternatives-for-react-native-web-4h28).

So if you want to use RN/RNW then either of these seems the way to go, instead of using Chakra UI.

Update: [NativeBase](nativebase.io) seems to be the most full-fledged alternative to Chakra UI for native, since it has styling baked in and a wide range of components. [Magnus UI](https://magnus-ui.com/) also comes with some polished RN components. [Dripsy is an unstyled library](https://github.com/chakra-ui/chakra-ui/issues/183#issuecomment-944404431), but you could easily use Dripsy as the building blocks to make a Chakra-like design system on top.

If you are determined to use Chakra UI on mobile, and are willing to sacrifice using RN/RNW, there is another option.

## Capacitor - To get Chakra UI in a mobile app, with a big caveat

Instead of using React Native (RN), a different option to get to use Chakra UI on mobile (and other platforms) would be to use [Capacitor](https://capacitorjs.com/), which is a native runtime/bridge for webapps (think 'Electron for mobile'). 

Capacitor supports iOS, Android and PWAs. There are also a [community plugin ](https://github.com/capacitor-community/electron) that [deploys Capacitor to Electron](https://capacitorjs.com/blog/announcing-capacitor-3-0-beta), opening up Capacitor apps to MacOS, Linux, Windows etc.

>Because Capacitor provides a native runtime environment for web apps, that means it can be used to turn any React web app into a native app. So apps using Material-UI or Chakra or Prime or Ant or Ionic Framework, or any other React UI library, can be turned into native apps using Capacitor (see our examples repo for real code in a variety of libraries).
>
>This simply isn’t possible with React Native. **Most popular React UI libraries target the web and react-dom, and most web libraries use web technologies like CSS that aren’t supported in React Native (at least not in their native format)**

https://capacitorjs.com/blog/native-react-apps-without-react-native

NB: Using Capacitor in practise means **bundling your website inside the app, NOT loading it on demand (via a url)**. That is [the recommended option from Capacitor’s creator Max Lynch](https://forum.ionicframework.com/t/apple-app-store-approval-issue-with-this/199417/5), since if not: _"Apple will likely reject your app since it is not “self-contained."_. To make it self-contained, you can do a [NextJS static export](https://nextjs.org/docs/advanced-features/static-html-export), for [example](https://twitter.com/rauchg/status/1342929084221812737?s=20). Sadly, for distribution, this means going through the App Store process, and asking clients to update their app for every code change (many will thus be out of date). Unless you use a service such as [CodePush for Capacitor](https://github.com/areo/capacitor-codepush). Never mind the weirdness of using a code distribution tool for native apps, just to _serve_ users with fresh HTML, CSS and JS...

The End.

Correct me if I'm wrong in any of this. This is at least what my research has turned up. Hope it helps someone.

Feel free to share alternative solutions or general approaches in the comments.